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: releng/6.3/sys/compat/svr4/svr4_stream.c 148131 2005-07-18 19:48:13Z jhb $");
   40 
   41 #include "opt_compat.h"
   42 #include "opt_ktrace.h"
   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 *, 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         char *path;
  513 {
  514         struct stat st;
  515         int error;
  516 
  517         error = kern_lstat(td, path, UIO_SYSSPACE, &st);
  518 
  519         /*
  520          * Make sure we are dealing with a mode 0 named pipe.
  521          */
  522         if ((st.st_mode & S_IFMT) != S_IFIFO)
  523                 return (0);
  524 
  525         if ((st.st_mode & ALLPERMS) != 0)
  526                 return (0);
  527 
  528         error = kern_unlink(td, path, UIO_SYSSPACE);
  529         if (error)
  530                 DPRINTF(("clean_pipe: unlink failed %d\n", error));
  531         return (error);
  532 }
  533 
  534 
  535 static void
  536 sockaddr_to_netaddr_in(sc, sain)
  537         struct svr4_strmcmd *sc;
  538         const struct sockaddr_in *sain;
  539 {
  540         struct svr4_netaddr_in *na;
  541         na = SVR4_ADDROF(sc);
  542 
  543         na->family = sain->sin_family;
  544         na->port = sain->sin_port;
  545         na->addr = sain->sin_addr.s_addr;
  546         DPRINTF(("sockaddr_in -> netaddr %d %d %lx\n", na->family, na->port,
  547                  na->addr));
  548 }
  549 
  550 
  551 static void
  552 sockaddr_to_netaddr_un(sc, saun)
  553         struct svr4_strmcmd *sc;
  554         const struct sockaddr_un *saun;
  555 {
  556         struct svr4_netaddr_un *na;
  557         char *dst, *edst = ((char *) sc) + sc->offs + sizeof(na->family) + 1  -
  558             sizeof(*sc);
  559         const char *src;
  560 
  561         na = SVR4_ADDROF(sc);
  562         na->family = saun->sun_family;
  563         for (src = saun->sun_path, dst = na->path; (*dst++ = *src++) != '\0'; )
  564                 if (dst == edst)
  565                         break;
  566         DPRINTF(("sockaddr_un -> netaddr %d %s\n", na->family, na->path));
  567 }
  568 
  569 
  570 static void
  571 netaddr_to_sockaddr_in(sain, sc)
  572         struct sockaddr_in *sain;
  573         const struct svr4_strmcmd *sc;
  574 {
  575         const struct svr4_netaddr_in *na;
  576 
  577 
  578         na = SVR4_C_ADDROF(sc);
  579         memset(sain, 0, sizeof(*sain));
  580         sain->sin_len = sizeof(*sain);
  581         sain->sin_family = na->family;
  582         sain->sin_port = na->port;
  583         sain->sin_addr.s_addr = na->addr;
  584         DPRINTF(("netaddr -> sockaddr_in %d %d %x\n", sain->sin_family,
  585                  sain->sin_port, sain->sin_addr.s_addr));
  586 }
  587 
  588 
  589 static void
  590 netaddr_to_sockaddr_un(saun, sc)
  591         struct sockaddr_un *saun;
  592         const struct svr4_strmcmd *sc;
  593 {
  594         const struct svr4_netaddr_un *na;
  595         char *dst, *edst = &saun->sun_path[sizeof(saun->sun_path) - 1];
  596         const char *src;
  597 
  598         na = SVR4_C_ADDROF(sc);
  599         memset(saun, 0, sizeof(*saun));
  600         saun->sun_family = na->family;
  601         for (src = na->path, dst = saun->sun_path; (*dst++ = *src++) != '\0'; )
  602                 if (dst == edst)
  603                         break;
  604         saun->sun_len = dst - saun->sun_path;
  605         DPRINTF(("netaddr -> sockaddr_un %d %s\n", saun->sun_family,
  606                  saun->sun_path));
  607 }
  608 
  609 
  610 static void
  611 getparm(fp, pa)
  612         struct file *fp;
  613         struct svr4_si_sockparms *pa;
  614 {
  615         struct svr4_strm *st;
  616         struct socket *so;
  617 
  618         st = svr4_stream_get(fp);
  619         if (st == NULL)
  620                 return;
  621 
  622         so = fp->f_data;
  623 
  624         pa->family = st->s_family;
  625 
  626         switch (so->so_type) {
  627         case SOCK_DGRAM:
  628                 pa->type = SVR4_T_CLTS;
  629                 pa->protocol = IPPROTO_UDP;
  630                 DPRINTF(("getparm(dgram)\n"));
  631                 return;
  632 
  633         case SOCK_STREAM:
  634                 pa->type = SVR4_T_COTS;  /* What about T_COTS_ORD? XXX */
  635                 pa->protocol = IPPROTO_IP;
  636                 DPRINTF(("getparm(stream)\n"));
  637                 return;
  638 
  639         case SOCK_RAW:
  640                 pa->type = SVR4_T_CLTS;
  641                 pa->protocol = IPPROTO_RAW;
  642                 DPRINTF(("getparm(raw)\n"));
  643                 return;
  644 
  645         default:
  646                 pa->type = 0;
  647                 pa->protocol = 0;
  648                 DPRINTF(("getparm(type %d?)\n", so->so_type));
  649                 return;
  650         }
  651 }
  652 
  653 
  654 static int
  655 si_ogetudata(fp, fd, ioc, td)
  656         struct file             *fp;
  657         int                      fd;
  658         struct svr4_strioctl    *ioc;
  659         struct thread           *td;
  660 {
  661         int error;
  662         struct svr4_si_oudata ud;
  663         struct svr4_si_sockparms pa;
  664 
  665         if (ioc->len != sizeof(ud) && ioc->len != sizeof(ud) - sizeof(int)) {
  666                 DPRINTF(("SI_OGETUDATA: Wrong size %d != %d\n",
  667                          sizeof(ud), ioc->len));
  668                 return EINVAL;
  669         }
  670 
  671         if ((error = copyin(ioc->buf, &ud, sizeof(ud))) != 0)
  672                 return error;
  673 
  674         getparm(fp, &pa);
  675 
  676         switch (pa.family) {
  677         case AF_INET:
  678             ud.tidusize = 16384;
  679             ud.addrsize = sizeof(struct svr4_sockaddr_in);
  680             if (pa.type == SVR4_SOCK_STREAM) 
  681                     ud.etsdusize = 1;
  682             else
  683                     ud.etsdusize = 0;
  684             break;
  685 
  686         case AF_LOCAL:
  687             ud.tidusize = 65536;
  688             ud.addrsize = 128;
  689             ud.etsdusize = 128;
  690             break;
  691 
  692         default:
  693             DPRINTF(("SI_OGETUDATA: Unsupported address family %d\n",
  694                      pa.family));
  695             return ENOSYS;
  696         }
  697 
  698         /* I have no idea what these should be! */
  699         ud.optsize = 128;
  700         ud.tsdusize = 128;
  701 
  702         ud.servtype = pa.type;
  703 
  704         /* XXX: Fixme */
  705         ud.so_state = 0;
  706         ud.so_options = 0;
  707         return copyout(&ud, ioc->buf, ioc->len);
  708 }
  709 
  710 
  711 static int
  712 si_sockparams(fp, fd, ioc, td)
  713         struct file             *fp;
  714         int                      fd;
  715         struct svr4_strioctl    *ioc;
  716         struct thread           *td;
  717 {
  718         struct svr4_si_sockparms pa;
  719 
  720         getparm(fp, &pa);
  721         return copyout(&pa, ioc->buf, sizeof(pa));
  722 }
  723 
  724 
  725 static int
  726 si_listen(fp, fd, ioc, td)
  727         struct file             *fp;
  728         int                      fd;
  729         struct svr4_strioctl    *ioc;
  730         struct thread           *td;
  731 {
  732         int error;
  733         struct svr4_strm *st = svr4_stream_get(fp);
  734         struct svr4_strmcmd lst;
  735         struct listen_args la;
  736 
  737         if (st == NULL)
  738                 return EINVAL;
  739 
  740         if (ioc->len < 0 || ioc->len > sizeof(lst))
  741                 return EINVAL;
  742 
  743         if ((error = copyin(ioc->buf, &lst, ioc->len)) != 0)
  744                 return error;
  745 
  746         if (lst.cmd != SVR4_TI_OLD_BIND_REQUEST) {
  747                 DPRINTF(("si_listen: bad request %ld\n", lst.cmd));
  748                 return EINVAL;
  749         }
  750 
  751         /*
  752          * We are making assumptions again...
  753          */
  754         la.s = fd;
  755         DPRINTF(("SI_LISTEN: fileno %d backlog = %d\n", fd, 5));
  756         la.backlog = 5;
  757 
  758         if ((error = listen(td, &la)) != 0) {
  759                 DPRINTF(("SI_LISTEN: listen failed %d\n", error));
  760                 return error;
  761         }
  762 
  763         st->s_cmd = SVR4_TI__ACCEPT_WAIT;
  764         lst.cmd = SVR4_TI_BIND_REPLY;
  765 
  766         switch (st->s_family) {
  767         case AF_INET:
  768                 /* XXX: Fill the length here */
  769                 break;
  770 
  771         case AF_LOCAL:
  772                 lst.len = 140;
  773                 lst.pad[28] = 0x00000000;       /* magic again */
  774                 lst.pad[29] = 0x00000800;       /* magic again */
  775                 lst.pad[30] = 0x80001400;       /* magic again */
  776                 break;
  777 
  778         default:
  779                 DPRINTF(("SI_LISTEN: Unsupported address family %d\n",
  780                     st->s_family));
  781                 return ENOSYS;
  782         }
  783 
  784 
  785         if ((error = copyout(&lst, ioc->buf, ioc->len)) != 0)
  786                 return error;
  787 
  788         return 0;
  789 }
  790 
  791 
  792 static int
  793 si_getudata(fp, fd, ioc, td)
  794         struct file             *fp;
  795         int                      fd;
  796         struct svr4_strioctl    *ioc;
  797         struct thread           *td;
  798 {
  799         int error;
  800         struct svr4_si_udata ud;
  801 
  802         if (sizeof(ud) != ioc->len) {
  803                 DPRINTF(("SI_GETUDATA: Wrong size %d != %d\n",
  804                          sizeof(ud), ioc->len));
  805                 return EINVAL;
  806         }
  807 
  808         if ((error = copyin(ioc->buf, &ud, sizeof(ud))) != 0)
  809                 return error;
  810 
  811         getparm(fp, &ud.sockparms);
  812 
  813         switch (ud.sockparms.family) {
  814         case AF_INET:
  815             DPRINTF(("getudata_inet\n"));
  816             ud.tidusize = 16384;
  817             ud.tsdusize = 16384;
  818             ud.addrsize = sizeof(struct svr4_sockaddr_in);
  819             if (ud.sockparms.type == SVR4_SOCK_STREAM) 
  820                     ud.etsdusize = 1;
  821             else
  822                     ud.etsdusize = 0;
  823             ud.optsize = 0;
  824             break;
  825 
  826         case AF_LOCAL:
  827             DPRINTF(("getudata_local\n"));
  828             ud.tidusize = 65536;
  829             ud.tsdusize = 128;
  830             ud.addrsize = 128;
  831             ud.etsdusize = 128;
  832             ud.optsize = 128;
  833             break;
  834 
  835         default:
  836             DPRINTF(("SI_GETUDATA: Unsupported address family %d\n",
  837                      ud.sockparms.family));
  838             return ENOSYS;
  839         }
  840 
  841 
  842         ud.servtype = ud.sockparms.type;
  843         DPRINTF(("ud.servtype = %d\n", ud.servtype));
  844         /* XXX: Fixme */
  845         ud.so_state = 0;
  846         ud.so_options = 0;
  847         return copyout(&ud, ioc->buf, sizeof(ud));
  848 }
  849 
  850 
  851 static int
  852 si_shutdown(fp, fd, ioc, td)
  853         struct file             *fp;
  854         int                      fd;
  855         struct svr4_strioctl    *ioc;
  856         struct thread           *td;
  857 {
  858         int error;
  859         struct shutdown_args ap;
  860 
  861         if (ioc->len != sizeof(ap.how)) {
  862                 DPRINTF(("SI_SHUTDOWN: Wrong size %d != %d\n",
  863                          sizeof(ap.how), ioc->len));
  864                 return EINVAL;
  865         }
  866 
  867         if ((error = copyin(ioc->buf, &ap.how, ioc->len)) != 0)
  868                 return error;
  869 
  870         ap.s = fd;
  871 
  872         return shutdown(td, &ap);
  873 }
  874 
  875 
  876 static int
  877 sockmod(fp, fd, ioc, td)
  878         struct file             *fp;
  879         int                      fd;
  880         struct svr4_strioctl    *ioc;
  881         struct thread           *td;
  882 {
  883         switch (ioc->cmd) {
  884         case SVR4_SI_OGETUDATA:
  885                 DPRINTF(("SI_OGETUDATA\n"));
  886                 return si_ogetudata(fp, fd, ioc, td);
  887 
  888         case SVR4_SI_SHUTDOWN:
  889                 DPRINTF(("SI_SHUTDOWN\n"));
  890                 return si_shutdown(fp, fd, ioc, td);
  891 
  892         case SVR4_SI_LISTEN:
  893                 DPRINTF(("SI_LISTEN\n"));
  894                 return si_listen(fp, fd, ioc, td);
  895 
  896         case SVR4_SI_SETMYNAME:
  897                 DPRINTF(("SI_SETMYNAME\n"));
  898                 return 0;
  899 
  900         case SVR4_SI_SETPEERNAME:
  901                 DPRINTF(("SI_SETPEERNAME\n"));
  902                 return 0;
  903 
  904         case SVR4_SI_GETINTRANSIT:
  905                 DPRINTF(("SI_GETINTRANSIT\n"));
  906                 return 0;
  907 
  908         case SVR4_SI_TCL_LINK:
  909                 DPRINTF(("SI_TCL_LINK\n"));
  910                 return 0;
  911 
  912         case SVR4_SI_TCL_UNLINK:
  913                 DPRINTF(("SI_TCL_UNLINK\n"));
  914                 return 0;
  915 
  916         case SVR4_SI_SOCKPARAMS:
  917                 DPRINTF(("SI_SOCKPARAMS\n"));
  918                 return si_sockparams(fp, fd, ioc, td);
  919 
  920         case SVR4_SI_GETUDATA:
  921                 DPRINTF(("SI_GETUDATA\n"));
  922                 return si_getudata(fp, fd, ioc, td);
  923 
  924         default:
  925                 DPRINTF(("Unknown sockmod ioctl %lx\n", ioc->cmd));
  926                 return 0;
  927 
  928         }
  929 }
  930 
  931 
  932 static int
  933 ti_getinfo(fp, fd, ioc, td)
  934         struct file             *fp;
  935         int                      fd;
  936         struct svr4_strioctl    *ioc;
  937         struct thread           *td;
  938 {
  939         int error;
  940         struct svr4_infocmd info;
  941 
  942         memset(&info, 0, sizeof(info));
  943 
  944         if (ioc->len < 0 || ioc->len > sizeof(info))
  945                 return EINVAL;
  946 
  947         if ((error = copyin(ioc->buf, &info, ioc->len)) != 0)
  948                 return error;
  949 
  950         if (info.cmd != SVR4_TI_INFO_REQUEST)
  951                 return EINVAL;
  952 
  953         info.cmd = SVR4_TI_INFO_REPLY;
  954         info.tsdu = 0;
  955         info.etsdu = 1;
  956         info.cdata = -2;
  957         info.ddata = -2;
  958         info.addr = 16;
  959         info.opt = -1;
  960         info.tidu = 16384;
  961         info.serv = 2;
  962         info.current = 0;
  963         info.provider = 2;
  964 
  965         ioc->len = sizeof(info);
  966         if ((error = copyout(&info, ioc->buf, ioc->len)) != 0)
  967                 return error;
  968 
  969         return 0;
  970 }
  971 
  972 
  973 static int
  974 ti_bind(fp, fd, ioc, td)
  975         struct file             *fp;
  976         int                      fd;
  977         struct svr4_strioctl    *ioc;
  978         struct thread           *td;
  979 {
  980         int error;
  981         struct svr4_strm *st = svr4_stream_get(fp);
  982         struct sockaddr_in sain;
  983         struct sockaddr_un saun;
  984         caddr_t sg;
  985         void *skp, *sup = NULL;
  986         int sasize;
  987         struct svr4_strmcmd bnd;
  988         struct bind_args ba;
  989 
  990         if (st == NULL) {
  991                 DPRINTF(("ti_bind: bad file descriptor\n"));
  992                 return EINVAL;
  993         }
  994 
  995         if (ioc->len < 0 || ioc->len > sizeof(bnd))
  996                 return EINVAL;
  997 
  998         if ((error = copyin(ioc->buf, &bnd, ioc->len)) != 0)
  999                 return error;
 1000 
 1001         if (bnd.cmd != SVR4_TI_OLD_BIND_REQUEST) {
 1002                 DPRINTF(("ti_bind: bad request %ld\n", bnd.cmd));
 1003                 return EINVAL;
 1004         }
 1005 
 1006         switch (st->s_family) {
 1007         case AF_INET:
 1008                 skp = &sain;
 1009                 sasize = sizeof(sain);
 1010 
 1011                 if (bnd.offs == 0)
 1012                         goto reply;
 1013 
 1014                 netaddr_to_sockaddr_in(&sain, &bnd);
 1015 
 1016                 DPRINTF(("TI_BIND: fam %d, port %d, addr %x\n",
 1017                          sain.sin_family, sain.sin_port,
 1018                          sain.sin_addr.s_addr));
 1019                 break;
 1020 
 1021         case AF_LOCAL:
 1022                 skp = &saun;
 1023                 sasize = sizeof(saun);
 1024                 if (bnd.offs == 0)
 1025                         goto reply;
 1026 
 1027                 netaddr_to_sockaddr_un(&saun, &bnd);
 1028 
 1029                 if (saun.sun_path[0] == '\0')
 1030                         goto reply;
 1031 
 1032                 DPRINTF(("TI_BIND: fam %d, path %s\n",
 1033                          saun.sun_family, saun.sun_path));
 1034 
 1035                 if ((error = clean_pipe(td, saun.sun_path)) != 0)
 1036                         return error;
 1037 
 1038                 bnd.pad[28] = 0x00001000;       /* magic again */
 1039                 break;
 1040 
 1041         default:
 1042                 DPRINTF(("TI_BIND: Unsupported address family %d\n",
 1043                          st->s_family));
 1044                 return ENOSYS;
 1045         }
 1046 
 1047         sg = stackgap_init();
 1048         sup = stackgap_alloc(&sg, sasize);
 1049 
 1050         if ((error = copyout(skp, sup, sasize)) != 0)
 1051                 return error;
 1052 
 1053         ba.s = fd;
 1054         DPRINTF(("TI_BIND: fileno %d\n", fd));
 1055         ba.name = (void *) sup;
 1056         ba.namelen = sasize;
 1057 
 1058         if ((error = bind(td, &ba)) != 0) {
 1059                 DPRINTF(("TI_BIND: bind failed %d\n", error));
 1060                 return error;
 1061         }
 1062 
 1063 reply:
 1064         if (sup == NULL) {
 1065                 memset(&bnd, 0, sizeof(bnd));
 1066                 bnd.len = sasize + 4;
 1067                 bnd.offs = 0x10;        /* XXX */
 1068         }
 1069 
 1070         bnd.cmd = SVR4_TI_BIND_REPLY;
 1071 
 1072         if ((error = copyout(&bnd, ioc->buf, ioc->len)) != 0)
 1073                 return error;
 1074 
 1075         return 0;
 1076 }
 1077 
 1078 
 1079 static int
 1080 timod(fp, fd, ioc, td)
 1081         struct file             *fp;
 1082         int                      fd;
 1083         struct svr4_strioctl    *ioc;
 1084         struct thread           *td;
 1085 {
 1086         switch (ioc->cmd) {
 1087         case SVR4_TI_GETINFO:
 1088                 DPRINTF(("TI_GETINFO\n"));
 1089                 return ti_getinfo(fp, fd, ioc, td);
 1090 
 1091         case SVR4_TI_OPTMGMT:
 1092                 DPRINTF(("TI_OPTMGMT\n"));
 1093                 return 0;
 1094 
 1095         case SVR4_TI_BIND:
 1096                 DPRINTF(("TI_BIND\n"));
 1097                 return ti_bind(fp, fd, ioc, td);
 1098 
 1099         case SVR4_TI_UNBIND:
 1100                 DPRINTF(("TI_UNBIND\n"));
 1101                 return 0;
 1102 
 1103         default:
 1104                 DPRINTF(("Unknown timod ioctl %lx\n", ioc->cmd));
 1105                 return 0;
 1106         }
 1107 }
 1108 
 1109 
 1110 int
 1111 svr4_stream_ti_ioctl(fp, td, retval, fd, cmd, dat)
 1112         struct file *fp;
 1113         struct thread *td;
 1114         register_t *retval;
 1115         int fd;
 1116         u_long cmd;
 1117         caddr_t dat;
 1118 {
 1119         struct svr4_strbuf skb, *sub = (struct svr4_strbuf *) dat;
 1120         struct svr4_strm *st = svr4_stream_get(fp);
 1121         int error;
 1122         void *skp, *sup;
 1123         struct sockaddr_in sain;
 1124         struct sockaddr_un saun;
 1125         struct svr4_strmcmd sc;
 1126         int sasize, oldsasize;
 1127         caddr_t sg;
 1128         int *lenp;
 1129 
 1130         DPRINTF(("svr4_stream_ti_ioctl\n"));
 1131 
 1132         if (st == NULL)
 1133                 return EINVAL;
 1134 
 1135         sc.offs = 0x10;
 1136         
 1137         if ((error = copyin(sub, &skb, sizeof(skb))) != 0) {
 1138                 DPRINTF(("ti_ioctl: error copying in strbuf\n"));
 1139                 return error;
 1140         }
 1141 
 1142         switch (st->s_family) {
 1143         case AF_INET:
 1144                 skp = &sain;
 1145                 sasize = sizeof(sain);
 1146                 break;
 1147 
 1148         case AF_LOCAL:
 1149                 skp = &saun;
 1150                 sasize = sizeof(saun);
 1151                 break;
 1152 
 1153         default:
 1154                 DPRINTF(("ti_ioctl: Unsupported address family %d\n",
 1155                          st->s_family));
 1156                 return ENOSYS;
 1157         }
 1158 
 1159         sg = stackgap_init();
 1160         sup = stackgap_alloc(&sg, sasize);
 1161         lenp = stackgap_alloc(&sg, sizeof(*lenp));
 1162 
 1163         if ((error = copyout(&sasize, lenp, sizeof(*lenp))) != 0) {
 1164                 DPRINTF(("ti_ioctl: error copying out lenp\n"));
 1165                 return error;
 1166         }
 1167 
 1168         switch (cmd) {
 1169         case SVR4_TI_GETMYNAME:
 1170                 DPRINTF(("TI_GETMYNAME\n"));
 1171                 {
 1172                         struct getsockname_args ap;
 1173                         ap.fdes = fd;
 1174                         ap.asa = sup;
 1175                         ap.alen = lenp;
 1176                         if ((error = getsockname(td, &ap)) != 0) {
 1177                                 DPRINTF(("ti_ioctl: getsockname error\n"));
 1178                                 return error;
 1179                         }
 1180                 }
 1181                 break;
 1182 
 1183         case SVR4_TI_GETPEERNAME:
 1184                 DPRINTF(("TI_GETPEERNAME\n"));
 1185                 {
 1186                         struct getpeername_args ap;
 1187                         ap.fdes = fd;
 1188                         ap.asa = sup;
 1189                         ap.alen = lenp;
 1190                         if ((error = getpeername(td, &ap)) != 0) {
 1191                                 DPRINTF(("ti_ioctl: getpeername error\n"));
 1192                                 return error;
 1193                         }
 1194                 }
 1195                 break;
 1196 
 1197         case SVR4_TI_SETMYNAME:
 1198                 DPRINTF(("TI_SETMYNAME\n"));
 1199                 return 0;
 1200 
 1201         case SVR4_TI_SETPEERNAME:
 1202                 DPRINTF(("TI_SETPEERNAME\n"));
 1203                 return 0;
 1204         default:
 1205                 DPRINTF(("ti_ioctl: Unknown ioctl %lx\n", cmd));
 1206                 return ENOSYS;
 1207         }
 1208 
 1209         if ((error = copyin(sup, skp, sasize)) != 0) {
 1210                 DPRINTF(("ti_ioctl: error copying in socket data\n"));
 1211                 return error;
 1212         }
 1213 
 1214         oldsasize = sasize;
 1215 
 1216         if ((error = copyin(lenp, &sasize, sizeof(*lenp))) != 0) {
 1217                 DPRINTF(("ti_ioctl: error copying in socket size\n"));
 1218                 return error;
 1219         }
 1220 
 1221         if (sasize < 0 || sasize > oldsasize)
 1222                 return EINVAL;
 1223 
 1224         switch (st->s_family) {
 1225         case AF_INET:
 1226                 sockaddr_to_netaddr_in(&sc, &sain);
 1227                 skb.len = sasize;
 1228                 break;
 1229 
 1230         case AF_LOCAL:
 1231                 sockaddr_to_netaddr_un(&sc, &saun);
 1232                 skb.len = sasize + 4;
 1233                 break;
 1234 
 1235         default:
 1236                 return ENOSYS;
 1237         }
 1238 
 1239 
 1240         if ((error = copyout(SVR4_ADDROF(&sc), skb.buf, sasize)) != 0) {
 1241                 DPRINTF(("ti_ioctl: error copying out socket data\n"));
 1242                 return error;
 1243         }
 1244 
 1245 
 1246         if ((error = copyout(&skb, sub, sizeof(skb))) != 0) {
 1247                 DPRINTF(("ti_ioctl: error copying out strbuf\n"));
 1248                 return error;
 1249         }
 1250 
 1251         return error;
 1252 }
 1253 
 1254 
 1255 
 1256 
 1257 static int
 1258 i_nread(fp, td, retval, fd, cmd, dat)
 1259         struct file *fp;
 1260         struct thread *td;
 1261         register_t *retval;
 1262         int fd;
 1263         u_long cmd;
 1264         caddr_t dat;
 1265 {
 1266         int error;
 1267         int nread = 0;  
 1268 
 1269         /*
 1270          * We are supposed to return the message length in nread, and the
 1271          * number of messages in retval. We don't have the notion of number
 1272          * of stream messages, so we just find out if we have any bytes waiting
 1273          * for us, and if we do, then we assume that we have at least one
 1274          * message waiting for us.
 1275          */
 1276         if ((error = fo_ioctl(fp, FIONREAD, (caddr_t) &nread, td->td_ucred,
 1277             td)) != 0)
 1278                 return error;
 1279 
 1280         if (nread != 0)
 1281                 *retval = 1;
 1282         else
 1283                 *retval = 0;
 1284 
 1285         return copyout(&nread, dat, sizeof(nread));
 1286 }
 1287 
 1288 static int
 1289 i_fdinsert(fp, td, retval, fd, cmd, dat)
 1290         struct file *fp;
 1291         struct thread *td;
 1292         register_t *retval;
 1293         int fd;
 1294         u_long cmd;
 1295         caddr_t dat;
 1296 {
 1297         /*
 1298          * Major hack again here. We assume that we are using this to
 1299          * implement accept(2). If that is the case, we have already
 1300          * called accept, and we have stored the file descriptor in
 1301          * afd. We find the file descriptor that the code wants to use
 1302          * in fd insert, and then we dup2() our accepted file descriptor
 1303          * to it.
 1304          */
 1305         int error;
 1306         struct svr4_strm *st = svr4_stream_get(fp);
 1307         struct svr4_strfdinsert fdi;
 1308         struct dup2_args d2p;
 1309         struct close_args clp;
 1310 
 1311         if (st == NULL) {
 1312                 DPRINTF(("fdinsert: bad file type\n"));
 1313                 return EINVAL;
 1314         }
 1315 
 1316         if (st->s_afd == -1) {
 1317                 DPRINTF(("fdinsert: accept fd not found\n"));
 1318                 return ENOENT;
 1319         }
 1320 
 1321         if ((error = copyin(dat, &fdi, sizeof(fdi))) != 0) {
 1322                 DPRINTF(("fdinsert: copyin failed %d\n", error));
 1323                 return error;
 1324         }
 1325 
 1326         d2p.from = st->s_afd;
 1327         d2p.to = fdi.fd;
 1328 
 1329         if ((error = dup2(td, &d2p)) != 0) {
 1330                 DPRINTF(("fdinsert: dup2(%d, %d) failed %d\n", 
 1331                     st->s_afd, fdi.fd, error));
 1332                 return error;
 1333         }
 1334 
 1335         clp.fd = st->s_afd;
 1336 
 1337         if ((error = close(td, &clp)) != 0) {
 1338                 DPRINTF(("fdinsert: close(%d) failed %d\n", 
 1339                     st->s_afd, error));
 1340                 return error;
 1341         }
 1342 
 1343         st->s_afd = -1;
 1344 
 1345         *retval = 0;
 1346         return 0;
 1347 }
 1348 
 1349 
 1350 static int
 1351 _i_bind_rsvd(fp, td, retval, fd, cmd, dat)
 1352         struct file *fp;
 1353         struct thread *td;
 1354         register_t *retval;
 1355         int fd;
 1356         u_long cmd;
 1357         caddr_t dat;
 1358 {
 1359         struct mkfifo_args ap;
 1360 
 1361         /*
 1362          * This is a supposed to be a kernel and library only ioctl.
 1363          * It gets called before ti_bind, when we have a unix 
 1364          * socket, to physically create the socket transport and
 1365          * ``reserve'' it. I don't know how this get reserved inside
 1366          * the kernel, but we are going to create it nevertheless.
 1367          */
 1368         ap.path = dat;
 1369         ap.mode = S_IFIFO;
 1370 
 1371         return mkfifo(td, &ap);
 1372 }
 1373 
 1374 static int
 1375 _i_rele_rsvd(fp, td, retval, fd, cmd, dat)
 1376         struct file *fp;
 1377         struct thread *td;
 1378         register_t *retval;
 1379         int fd;
 1380         u_long cmd;
 1381         caddr_t dat;
 1382 {
 1383         struct unlink_args ap;
 1384 
 1385         /*
 1386          * This is a supposed to be a kernel and library only ioctl.
 1387          * I guess it is supposed to release the socket.
 1388          */
 1389         ap.path = dat;
 1390 
 1391         return unlink(td, &ap);
 1392 }
 1393 
 1394 static int
 1395 i_str(fp, td, retval, fd, cmd, dat)
 1396         struct file *fp;
 1397         struct thread *td;
 1398         register_t *retval;
 1399         int fd;
 1400         u_long cmd;
 1401         caddr_t dat;
 1402 {
 1403         int                      error;
 1404         struct svr4_strioctl     ioc;
 1405 
 1406         if ((error = copyin(dat, &ioc, sizeof(ioc))) != 0)
 1407                 return error;
 1408 
 1409 #ifdef DEBUG_SVR4
 1410         if ((error = show_ioc(">", &ioc)) != 0)
 1411                 return error;
 1412 #endif /* DEBUG_SVR4 */
 1413 
 1414         switch (ioc.cmd & 0xff00) {
 1415         case SVR4_SIMOD:
 1416                 if ((error = sockmod(fp, fd, &ioc, td)) != 0)
 1417                         return error;
 1418                 break;
 1419 
 1420         case SVR4_TIMOD:
 1421                 if ((error = timod(fp, fd, &ioc, td)) != 0)
 1422                         return error;
 1423                 break;
 1424 
 1425         default:
 1426                 DPRINTF(("Unimplemented module %c %ld\n",
 1427                          (char) (cmd >> 8), cmd & 0xff));
 1428                 return 0;
 1429         }
 1430 
 1431 #ifdef DEBUG_SVR4
 1432         if ((error = show_ioc("<", &ioc)) != 0)
 1433                 return error;
 1434 #endif /* DEBUG_SVR4 */
 1435         return copyout(&ioc, dat, sizeof(ioc));
 1436 }
 1437 
 1438 static int
 1439 i_setsig(fp, td, retval, fd, cmd, dat)
 1440         struct file *fp;
 1441         struct thread *td;
 1442         register_t *retval;
 1443         int fd;
 1444         u_long cmd;
 1445         caddr_t dat;
 1446 {
 1447         /* 
 1448          * This is the best we can do for now; we cannot generate
 1449          * signals only for specific events so the signal mask gets
 1450          * ignored; we save it just to pass it to a possible I_GETSIG...
 1451          *
 1452          * We alse have to fix the O_ASYNC fcntl bit, so the
 1453          * process will get SIGPOLLs.
 1454          */
 1455         int error;
 1456         register_t oflags, flags;
 1457         struct svr4_strm *st = svr4_stream_get(fp);
 1458 
 1459         if (st == NULL) {
 1460                 DPRINTF(("i_setsig: bad file descriptor\n"));
 1461                 return EINVAL;
 1462         }
 1463         /* get old status flags */
 1464         error = kern_fcntl(td, fd, F_GETFL, 0);
 1465         if (error)
 1466                 return (error);
 1467 
 1468         oflags = td->td_retval[0];
 1469 
 1470         /* update the flags */
 1471         if (dat != NULL) {
 1472                 int mask;
 1473 
 1474                 flags = oflags | O_ASYNC;
 1475                 if ((error = copyin(dat, &mask, sizeof(mask))) != 0) {
 1476                           DPRINTF(("i_setsig: bad eventmask pointer\n"));
 1477                           return error;
 1478                 }
 1479                 if (mask & SVR4_S_ALLMASK) {
 1480                           DPRINTF(("i_setsig: bad eventmask data %x\n", mask));
 1481                           return EINVAL;
 1482                 }
 1483                 st->s_eventmask = mask;
 1484         }
 1485         else {
 1486                 flags = oflags & ~O_ASYNC;
 1487                 st->s_eventmask = 0;
 1488         }
 1489 
 1490         /* set the new flags, if changed */
 1491         if (flags != oflags) {
 1492                 error = kern_fcntl(td, fd, F_SETFL, flags);
 1493                 if (error)
 1494                         return (error);
 1495                 flags = td->td_retval[0];
 1496         }
 1497 
 1498         /* set up SIGIO receiver if needed */
 1499         if (dat != NULL)
 1500                 return (kern_fcntl(td, fd, F_SETOWN, td->td_proc->p_pid));
 1501         return 0;
 1502 }
 1503 
 1504 static int
 1505 i_getsig(fp, td, retval, fd, cmd, dat)
 1506         struct file *fp;
 1507         struct thread *td;
 1508         register_t *retval;
 1509         int fd;
 1510         u_long cmd;
 1511         caddr_t dat;
 1512 {
 1513         int error;
 1514 
 1515         if (dat != NULL) {
 1516                 struct svr4_strm *st = svr4_stream_get(fp);
 1517 
 1518                 if (st == NULL) {
 1519                         DPRINTF(("i_getsig: bad file descriptor\n"));
 1520                         return EINVAL;
 1521                 }
 1522                 if ((error = copyout(&st->s_eventmask, dat, 
 1523                                      sizeof(st->s_eventmask))) != 0) {
 1524                         DPRINTF(("i_getsig: bad eventmask pointer\n"));
 1525                         return error;
 1526                 }
 1527         }
 1528         return 0;
 1529 }
 1530 
 1531 int
 1532 svr4_stream_ioctl(fp, td, retval, fd, cmd, dat)
 1533         struct file *fp;
 1534         struct thread *td;
 1535         register_t *retval;
 1536         int fd;
 1537         u_long cmd;
 1538         caddr_t dat;
 1539 {
 1540         *retval = 0;
 1541 
 1542         /*
 1543          * All the following stuff assumes "sockmod" is pushed...
 1544          */
 1545         switch (cmd) {
 1546         case SVR4_I_NREAD:
 1547                 DPRINTF(("I_NREAD\n"));
 1548                 return i_nread(fp, td, retval, fd, cmd, dat);
 1549 
 1550         case SVR4_I_PUSH:
 1551                 DPRINTF(("I_PUSH %p\n", dat));
 1552 #if defined(DEBUG_SVR4)
 1553                 show_strbuf((struct svr4_strbuf *)dat);
 1554 #endif
 1555                 return 0;
 1556 
 1557         case SVR4_I_POP:
 1558                 DPRINTF(("I_POP\n"));
 1559                 return 0;
 1560 
 1561         case SVR4_I_LOOK:
 1562                 DPRINTF(("I_LOOK\n"));
 1563                 return 0;
 1564 
 1565         case SVR4_I_FLUSH:
 1566                 DPRINTF(("I_FLUSH\n"));
 1567                 return 0;
 1568 
 1569         case SVR4_I_SRDOPT:
 1570                 DPRINTF(("I_SRDOPT\n"));
 1571                 return 0;
 1572 
 1573         case SVR4_I_GRDOPT:
 1574                 DPRINTF(("I_GRDOPT\n"));
 1575                 return 0;
 1576 
 1577         case SVR4_I_STR:
 1578                 DPRINTF(("I_STR\n"));
 1579                 return i_str(fp, td, retval, fd, cmd, dat);
 1580 
 1581         case SVR4_I_SETSIG:
 1582                 DPRINTF(("I_SETSIG\n"));
 1583                 return i_setsig(fp, td, retval, fd, cmd, dat);
 1584 
 1585         case SVR4_I_GETSIG:
 1586                 DPRINTF(("I_GETSIG\n"));
 1587                 return i_getsig(fp, td, retval, fd, cmd, dat);
 1588 
 1589         case SVR4_I_FIND:
 1590                 DPRINTF(("I_FIND\n"));
 1591                 /*
 1592                  * Here we are not pushing modules really, we just
 1593                  * pretend all are present
 1594                  */
 1595                 *retval = 0;
 1596                 return 0;
 1597 
 1598         case SVR4_I_LINK:
 1599                 DPRINTF(("I_LINK\n"));
 1600                 return 0;
 1601 
 1602         case SVR4_I_UNLINK:
 1603                 DPRINTF(("I_UNLINK\n"));
 1604                 return 0;
 1605 
 1606         case SVR4_I_ERECVFD:
 1607                 DPRINTF(("I_ERECVFD\n"));
 1608                 return 0;
 1609 
 1610         case SVR4_I_PEEK:
 1611                 DPRINTF(("I_PEEK\n"));
 1612                 return 0;
 1613 
 1614         case SVR4_I_FDINSERT:
 1615                 DPRINTF(("I_FDINSERT\n"));
 1616                 return i_fdinsert(fp, td, retval, fd, cmd, dat);
 1617 
 1618         case SVR4_I_SENDFD:
 1619                 DPRINTF(("I_SENDFD\n"));
 1620                 return 0;
 1621 
 1622         case SVR4_I_RECVFD:
 1623                 DPRINTF(("I_RECVFD\n"));
 1624                 return 0;
 1625 
 1626         case SVR4_I_SWROPT:
 1627                 DPRINTF(("I_SWROPT\n"));
 1628                 return 0;
 1629 
 1630         case SVR4_I_GWROPT:
 1631                 DPRINTF(("I_GWROPT\n"));
 1632                 return 0;
 1633 
 1634         case SVR4_I_LIST:
 1635                 DPRINTF(("I_LIST\n"));
 1636                 return 0;
 1637 
 1638         case SVR4_I_PLINK:
 1639                 DPRINTF(("I_PLINK\n"));
 1640                 return 0;
 1641 
 1642         case SVR4_I_PUNLINK:
 1643                 DPRINTF(("I_PUNLINK\n"));
 1644                 return 0;
 1645 
 1646         case SVR4_I_SETEV:
 1647                 DPRINTF(("I_SETEV\n"));
 1648                 return 0;
 1649 
 1650         case SVR4_I_GETEV:
 1651                 DPRINTF(("I_GETEV\n"));
 1652                 return 0;
 1653 
 1654         case SVR4_I_STREV:
 1655                 DPRINTF(("I_STREV\n"));
 1656                 return 0;
 1657 
 1658         case SVR4_I_UNSTREV:
 1659                 DPRINTF(("I_UNSTREV\n"));
 1660                 return 0;
 1661 
 1662         case SVR4_I_FLUSHBAND:
 1663                 DPRINTF(("I_FLUSHBAND\n"));
 1664                 return 0;
 1665 
 1666         case SVR4_I_CKBAND:
 1667                 DPRINTF(("I_CKBAND\n"));
 1668                 return 0;
 1669 
 1670         case SVR4_I_GETBAND:
 1671                 DPRINTF(("I_GETBANK\n"));
 1672                 return 0;
 1673 
 1674         case SVR4_I_ATMARK:
 1675                 DPRINTF(("I_ATMARK\n"));
 1676                 return 0;
 1677 
 1678         case SVR4_I_SETCLTIME:
 1679                 DPRINTF(("I_SETCLTIME\n"));
 1680                 return 0;
 1681 
 1682         case SVR4_I_GETCLTIME:
 1683                 DPRINTF(("I_GETCLTIME\n"));
 1684                 return 0;
 1685 
 1686         case SVR4_I_CANPUT:
 1687                 DPRINTF(("I_CANPUT\n"));
 1688                 return 0;
 1689 
 1690         case SVR4__I_BIND_RSVD:
 1691                 DPRINTF(("_I_BIND_RSVD\n"));
 1692                 return _i_bind_rsvd(fp, td, retval, fd, cmd, dat);
 1693 
 1694         case SVR4__I_RELE_RSVD:
 1695                 DPRINTF(("_I_RELE_RSVD\n"));
 1696                 return _i_rele_rsvd(fp, td, retval, fd, cmd, dat);
 1697 
 1698         default:
 1699                 DPRINTF(("unimpl cmd = %lx\n", cmd));
 1700                 break;
 1701         }
 1702 
 1703         return 0;
 1704 }
 1705 
 1706 
 1707 
 1708 int
 1709 svr4_sys_putmsg(td, uap)
 1710         register struct thread *td;
 1711         struct svr4_sys_putmsg_args *uap;
 1712 {
 1713         struct file     *fp;
 1714         int error;
 1715 
 1716         if ((error = fget(td, uap->fd, &fp)) != 0) {
 1717 #ifdef DEBUG_SVR4
 1718                 uprintf("putmsg: bad fp\n");
 1719 #endif
 1720                 return EBADF;
 1721         }
 1722         error = svr4_do_putmsg(td, uap, fp);
 1723         fdrop(fp, td);
 1724         return (error);
 1725 }
 1726 
 1727 static int
 1728 svr4_do_putmsg(td, uap, fp)
 1729         struct thread *td;
 1730         struct svr4_sys_putmsg_args *uap;
 1731         struct file     *fp;
 1732 {
 1733         struct svr4_strbuf dat, ctl;
 1734         struct svr4_strmcmd sc;
 1735         struct sockaddr_in sain;
 1736         struct sockaddr_un saun;
 1737         void *skp, *sup;
 1738         int sasize, *retval;
 1739         struct svr4_strm *st;
 1740         int error;
 1741         caddr_t sg;
 1742 
 1743         retval = td->td_retval;
 1744 
 1745 #ifdef DEBUG_SVR4
 1746         show_msg(">putmsg", uap->fd, uap->ctl,
 1747                  uap->dat, uap->flags);
 1748 #endif /* DEBUG_SVR4 */
 1749 
 1750         FILE_LOCK_ASSERT(fp, MA_NOTOWNED);
 1751 
 1752         if (uap->ctl != NULL) {
 1753           if ((error = copyin(uap->ctl, &ctl, sizeof(ctl))) != 0) {
 1754 #ifdef DEBUG_SVR4
 1755             uprintf("putmsg: copyin(): %d\n", error);
 1756 #endif
 1757             return error;
 1758           }
 1759         }
 1760         else
 1761                 ctl.len = -1;
 1762 
 1763         if (uap->dat != NULL) {
 1764           if ((error = copyin(uap->dat, &dat, sizeof(dat))) != 0) {
 1765 #ifdef DEBUG_SVR4
 1766             uprintf("putmsg: copyin(): %d (2)\n", error);
 1767 #endif
 1768             return error;
 1769           }
 1770         }
 1771         else
 1772                 dat.len = -1;
 1773 
 1774         /*
 1775          * Only for sockets for now.
 1776          */
 1777         if ((st = svr4_stream_get(fp)) == NULL) {
 1778                 DPRINTF(("putmsg: bad file type\n"));
 1779                 return EINVAL;
 1780         }
 1781 
 1782         if (ctl.len < 0 || ctl.len > sizeof(sc)) {
 1783                 DPRINTF(("putmsg: Bad control size %d != %d\n", ctl.len,
 1784                          sizeof(struct svr4_strmcmd)));
 1785                 return EINVAL;
 1786         }
 1787 
 1788         if ((error = copyin(ctl.buf, &sc, ctl.len)) != 0)
 1789                 return error;
 1790 
 1791         switch (st->s_family) {
 1792         case AF_INET:
 1793                 if (sc.len != sizeof(sain)) {
 1794                         if (sc.cmd == SVR4_TI_DATA_REQUEST) {
 1795                                 struct write_args wa;
 1796 
 1797                                 /* Solaris seems to use sc.cmd = 3 to
 1798                                  * send "expedited" data.  telnet uses
 1799                                  * this for options processing, sending EOF,
 1800                                  * etc.  I'm sure other things use it too.
 1801                                  * I don't have any documentation
 1802                                  * on it, so I'm making a guess that this
 1803                                  * is how it works. newton@atdot.dotat.org XXX
 1804                                  */
 1805                                 DPRINTF(("sending expedited data ??\n"));
 1806                                 wa.fd = uap->fd;
 1807                                 wa.buf = dat.buf;
 1808                                 wa.nbyte = dat.len;
 1809                                 return write(td, &wa);
 1810                         }
 1811                         DPRINTF(("putmsg: Invalid inet length %ld\n", sc.len));
 1812                         return EINVAL;
 1813                 }
 1814                 netaddr_to_sockaddr_in(&sain, &sc);
 1815                 skp = &sain;
 1816                 sasize = sizeof(sain);
 1817                 error = sain.sin_family != st->s_family;
 1818                 break;
 1819 
 1820         case AF_LOCAL:
 1821                 if (ctl.len == 8) {
 1822                         /* We are doing an accept; succeed */
 1823                         DPRINTF(("putmsg: Do nothing\n"));
 1824                         *retval = 0;
 1825                         return 0;
 1826                 }
 1827                 else {
 1828                         /* Maybe we've been given a device/inode pair */
 1829                         dev_t *dev = SVR4_ADDROF(&sc);
 1830                         ino_t *ino = (ino_t *) &dev[1];
 1831                         skp = svr4_find_socket(td, fp, *dev, *ino);
 1832                         if (skp == NULL) {
 1833                                 skp = &saun;
 1834                                 /* I guess we have it by name */
 1835                                 netaddr_to_sockaddr_un(skp, &sc);
 1836                         }
 1837                         sasize = sizeof(saun);
 1838                 }
 1839                 break;
 1840 
 1841         default:
 1842                 DPRINTF(("putmsg: Unsupported address family %d\n",
 1843                          st->s_family));
 1844                 return ENOSYS;
 1845         }
 1846 
 1847         sg = stackgap_init();
 1848         sup = stackgap_alloc(&sg, sasize);
 1849 
 1850         if ((error = copyout(skp, sup, sasize)) != 0)
 1851                 return error;
 1852 
 1853         switch (st->s_cmd = sc.cmd) {
 1854         case SVR4_TI_CONNECT_REQUEST:   /* connect      */
 1855                 {
 1856                         struct connect_args co;
 1857 
 1858                         co.s = uap->fd;
 1859                         co.name = (void *) sup;
 1860                         co.namelen = (int) sasize;
 1861                         
 1862                         return connect(td, &co);
 1863                 }
 1864 
 1865         case SVR4_TI_SENDTO_REQUEST:    /* sendto       */
 1866                 {
 1867                         struct msghdr msg;
 1868                         struct iovec aiov;
 1869 
 1870                         msg.msg_name = (caddr_t) sup;
 1871                         msg.msg_namelen = sasize;
 1872                         msg.msg_iov = &aiov;
 1873                         msg.msg_iovlen = 1;
 1874                         msg.msg_control = 0;
 1875                         msg.msg_flags = 0;
 1876                         aiov.iov_base = dat.buf;
 1877                         aiov.iov_len = dat.len;
 1878 #if 0
 1879                         error = so->so_proto->pr_usrreqs->pru_sosend(so, 0, 
 1880                                               uio, 0, 0, 0, uio->uio_td);
 1881 #endif
 1882                         error = svr4_sendit(td, uap->fd, &msg,
 1883                                        uap->flags);
 1884                         DPRINTF(("sendto_request error: %d\n", error));
 1885                         *retval = 0;
 1886                         return error;
 1887                 }
 1888 
 1889         default:
 1890                 DPRINTF(("putmsg: Unimplemented command %lx\n", sc.cmd));
 1891                 return ENOSYS;
 1892         }
 1893 }
 1894 
 1895 int
 1896 svr4_sys_getmsg(td, uap)
 1897         struct thread *td;
 1898         struct svr4_sys_getmsg_args *uap;
 1899 {
 1900         struct file     *fp;
 1901         int error;
 1902 
 1903         if ((error = fget(td, uap->fd, &fp)) != 0) {
 1904 #ifdef DEBUG_SVR4
 1905                 uprintf("getmsg: bad fp\n");
 1906 #endif
 1907                 return EBADF;
 1908         }
 1909         error = svr4_do_getmsg(td, uap, fp);
 1910         fdrop(fp, td);
 1911         return (error);
 1912 }
 1913 
 1914 int
 1915 svr4_do_getmsg(td, uap, fp)
 1916         register struct thread *td;
 1917         struct svr4_sys_getmsg_args *uap;
 1918         struct file *fp;
 1919 {
 1920         struct getpeername_args ga;
 1921         struct accept_args aa;
 1922         struct svr4_strbuf dat, ctl;
 1923         struct svr4_strmcmd sc;
 1924         int error, *retval;
 1925         struct msghdr msg;
 1926         struct iovec aiov;
 1927         struct sockaddr_in sain;
 1928         struct sockaddr_un saun;
 1929         void *skp, *sup;
 1930         int sasize;
 1931         struct svr4_strm *st;
 1932         int *flen;
 1933         int fl;
 1934         caddr_t sg;
 1935 
 1936         retval = td->td_retval;
 1937 
 1938         FILE_LOCK_ASSERT(fp, MA_NOTOWNED);
 1939 
 1940         memset(&sc, 0, sizeof(sc));
 1941 
 1942 #ifdef DEBUG_SVR4
 1943         show_msg(">getmsg", uap->fd, uap->ctl,
 1944                  uap->dat, 0);
 1945 #endif /* DEBUG_SVR4 */
 1946 
 1947         if (uap->ctl != NULL) {
 1948                 if ((error = copyin(uap->ctl, &ctl, sizeof(ctl))) != 0)
 1949                         return error;
 1950                 if (ctl.len < 0)
 1951                         return EINVAL;
 1952         }
 1953         else {
 1954                 ctl.len = -1;
 1955                 ctl.maxlen = 0;
 1956         }
 1957 
 1958         if (uap->dat != NULL) {
 1959                 if ((error = copyin(uap->dat, &dat, sizeof(dat))) != 0)
 1960                         return error;
 1961         }
 1962         else {
 1963                 dat.len = -1;
 1964                 dat.maxlen = 0;
 1965         }
 1966 
 1967         /*
 1968          * Only for sockets for now.
 1969          */
 1970         if ((st = svr4_stream_get(fp)) == NULL) {
 1971                 DPRINTF(("getmsg: bad file type\n"));
 1972                 return EINVAL;
 1973         }
 1974 
 1975         if (ctl.maxlen == -1 || dat.maxlen == -1) {
 1976                 DPRINTF(("getmsg: Cannot handle -1 maxlen (yet)\n"));
 1977                 return ENOSYS;
 1978         }
 1979 
 1980         switch (st->s_family) {
 1981         case AF_INET:
 1982                 skp = &sain;
 1983                 sasize = sizeof(sain);
 1984                 break;
 1985 
 1986         case AF_LOCAL:
 1987                 skp = &saun;
 1988                 sasize = sizeof(saun);
 1989                 break;
 1990 
 1991         default:
 1992                 DPRINTF(("getmsg: Unsupported address family %d\n",
 1993                          st->s_family));
 1994                 return ENOSYS;
 1995         }
 1996 
 1997         sg = stackgap_init();
 1998         sup = stackgap_alloc(&sg, sasize);
 1999         flen = (int *) stackgap_alloc(&sg, sizeof(*flen));
 2000 
 2001         fl = sasize;
 2002         if ((error = copyout(&fl, flen, sizeof(fl))) != 0)
 2003                 return error;
 2004 
 2005         switch (st->s_cmd) {
 2006         case SVR4_TI_CONNECT_REQUEST:
 2007                 DPRINTF(("getmsg: TI_CONNECT_REQUEST\n"));
 2008                 /*
 2009                  * We do the connect in one step, so the putmsg should
 2010                  * have gotten the error.
 2011                  */
 2012                 sc.cmd = SVR4_TI_OK_REPLY;
 2013                 sc.len = 0;
 2014 
 2015                 ctl.len = 8;
 2016                 dat.len = -1;
 2017                 fl = 1;
 2018                 st->s_cmd = sc.cmd;
 2019                 break;
 2020 
 2021         case SVR4_TI_OK_REPLY:
 2022                 DPRINTF(("getmsg: TI_OK_REPLY\n"));
 2023                 /*
 2024                  * We are immediately after a connect reply, so we send
 2025                  * a connect verification.
 2026                  */
 2027 
 2028                 ga.fdes = uap->fd;
 2029                 ga.asa = (void *) sup;
 2030                 ga.alen = flen;
 2031                 
 2032                 if ((error = getpeername(td, &ga)) != 0) {
 2033                         DPRINTF(("getmsg: getpeername failed %d\n", error));
 2034                         return error;
 2035                 }
 2036 
 2037                 if ((error = copyin(sup, skp, sasize)) != 0)
 2038                         return error;
 2039                 
 2040                 sc.cmd = SVR4_TI_CONNECT_REPLY;
 2041                 sc.pad[0] = 0x4;
 2042                 sc.offs = 0x18;
 2043                 sc.pad[1] = 0x14;
 2044                 sc.pad[2] = 0x04000402;
 2045 
 2046                 switch (st->s_family) {
 2047                 case AF_INET:
 2048                         sc.len = sasize;
 2049                         sockaddr_to_netaddr_in(&sc, &sain);
 2050                         break;
 2051 
 2052                 case AF_LOCAL:
 2053                         sc.len = sasize + 4;
 2054                         sockaddr_to_netaddr_un(&sc, &saun);
 2055                         break;
 2056 
 2057                 default:
 2058                         return ENOSYS;
 2059                 }
 2060 
 2061                 ctl.len = 40;
 2062                 dat.len = -1;
 2063                 fl = 0;
 2064                 st->s_cmd = sc.cmd;
 2065                 break;
 2066 
 2067         case SVR4_TI__ACCEPT_OK:
 2068                 DPRINTF(("getmsg: TI__ACCEPT_OK\n"));
 2069                 /*
 2070                  * We do the connect in one step, so the putmsg should
 2071                  * have gotten the error.
 2072                  */
 2073                 sc.cmd = SVR4_TI_OK_REPLY;
 2074                 sc.len = 1;
 2075 
 2076                 ctl.len = 8;
 2077                 dat.len = -1;
 2078                 fl = 1;
 2079                 st->s_cmd = SVR4_TI__ACCEPT_WAIT;
 2080                 break;
 2081 
 2082         case SVR4_TI__ACCEPT_WAIT:
 2083                 DPRINTF(("getmsg: TI__ACCEPT_WAIT\n"));
 2084                 /*
 2085                  * We are after a listen, so we try to accept...
 2086                  */
 2087                 aa.s = uap->fd;
 2088                 aa.name = (void *) sup;
 2089                 aa.anamelen = flen;
 2090                 
 2091                 if ((error = accept(td, &aa)) != 0) {
 2092                         DPRINTF(("getmsg: accept failed %d\n", error));
 2093                         return error;
 2094                 }
 2095 
 2096                 st->s_afd = *retval;
 2097 
 2098                 DPRINTF(("getmsg: Accept fd = %d\n", st->s_afd));
 2099 
 2100                 if ((error = copyin(sup, skp, sasize)) != 0)
 2101                         return error;
 2102                 
 2103                 sc.cmd = SVR4_TI_ACCEPT_REPLY;
 2104                 sc.offs = 0x18;
 2105                 sc.pad[0] = 0x0;
 2106 
 2107                 switch (st->s_family) {
 2108                 case AF_INET:
 2109                         sc.pad[1] = 0x28;
 2110                         sockaddr_to_netaddr_in(&sc, &sain);
 2111                         ctl.len = 40;
 2112                         sc.len = sasize;
 2113                         break;
 2114 
 2115                 case AF_LOCAL:
 2116                         sc.pad[1] = 0x00010000;
 2117                         sc.pad[2] = 0xf6bcdaa0; /* I don't know what that is */
 2118                         sc.pad[3] = 0x00010000;
 2119                         ctl.len = 134;
 2120                         sc.len = sasize + 4;
 2121                         break;
 2122 
 2123                 default:
 2124                         return ENOSYS;
 2125                 }
 2126 
 2127                 dat.len = -1;
 2128                 fl = 0;
 2129                 st->s_cmd = SVR4_TI__ACCEPT_OK;
 2130                 break;
 2131 
 2132         case SVR4_TI_SENDTO_REQUEST:
 2133                 DPRINTF(("getmsg: TI_SENDTO_REQUEST\n"));
 2134                 if (ctl.maxlen > 36 && ctl.len < 36)
 2135                     ctl.len = 36;
 2136 
 2137                 if (ctl.len > sizeof(sc))
 2138                         ctl.len = sizeof(sc);
 2139 
 2140                 if ((error = copyin(ctl.buf, &sc, ctl.len)) != 0)
 2141                         return error;
 2142 
 2143                 switch (st->s_family) {
 2144                 case AF_INET:
 2145                         sockaddr_to_netaddr_in(&sc, &sain);
 2146                         break;
 2147 
 2148                 case AF_LOCAL:
 2149                         sockaddr_to_netaddr_un(&sc, &saun);
 2150                         break;
 2151 
 2152                 default:
 2153                         return ENOSYS;
 2154                 }
 2155 
 2156                 msg.msg_name = (caddr_t) sup;
 2157                 msg.msg_namelen = sasize;
 2158                 msg.msg_iov = &aiov;
 2159                 msg.msg_iovlen = 1;
 2160                 msg.msg_control = 0;
 2161                 aiov.iov_base = dat.buf;
 2162                 aiov.iov_len = dat.maxlen;
 2163                 msg.msg_flags = 0;
 2164 
 2165                 error = svr4_recvit(td, uap->fd, &msg, (caddr_t) flen);
 2166 
 2167                 if (error) {
 2168                         DPRINTF(("getmsg: recvit failed %d\n", error));
 2169                         return error;
 2170                 }
 2171 
 2172                 if ((error = copyin(msg.msg_name, skp, sasize)) != 0)
 2173                         return error;
 2174 
 2175                 sc.cmd = SVR4_TI_RECVFROM_IND;
 2176 
 2177                 switch (st->s_family) {
 2178                 case AF_INET:
 2179                         sc.len = sasize;
 2180                         sockaddr_to_netaddr_in(&sc, &sain);
 2181                         break;
 2182 
 2183                 case AF_LOCAL:
 2184                         sc.len = sasize + 4;
 2185                         sockaddr_to_netaddr_un(&sc, &saun);
 2186                         break;
 2187 
 2188                 default:
 2189                         return ENOSYS;
 2190                 }
 2191 
 2192                 dat.len = *retval;
 2193                 fl = 0;
 2194                 st->s_cmd = sc.cmd;
 2195                 break;
 2196 
 2197         default:
 2198                 st->s_cmd = sc.cmd;
 2199                 if (st->s_cmd == SVR4_TI_CONNECT_REQUEST) {
 2200                         struct read_args ra;
 2201 
 2202                         /* More weirdness:  Again, I can't find documentation
 2203                          * to back this up, but when a process does a generic
 2204                          * "getmsg()" call it seems that the command field is
 2205                          * zero and the length of the data area is zero.  I
 2206                          * think processes expect getmsg() to fill in dat.len
 2207                          * after reading at most dat.maxlen octets from the
 2208                          * stream.  Since we're using sockets I can let 
 2209                          * read() look after it and frob return values
 2210                          * appropriately (or inappropriately :-)
 2211                          *   -- newton@atdot.dotat.org        XXX
 2212                          */
 2213                         ra.fd = uap->fd;
 2214                         ra.buf = dat.buf;
 2215                         ra.nbyte = dat.maxlen;
 2216                         if ((error = read(td, &ra)) != 0) {
 2217                                 return error;
 2218                         }
 2219                         dat.len = *retval;
 2220                         *retval = 0;
 2221                         st->s_cmd = SVR4_TI_SENDTO_REQUEST;
 2222                         break;
 2223                 }
 2224                 DPRINTF(("getmsg: Unknown state %x\n", st->s_cmd));
 2225                 return EINVAL;
 2226         }
 2227 
 2228         if (uap->ctl) {
 2229                 if (ctl.len > sizeof(sc))
 2230                         ctl.len = sizeof(sc);
 2231                 if (ctl.len != -1)
 2232                         if ((error = copyout(&sc, ctl.buf, ctl.len)) != 0)
 2233                                 return error;
 2234 
 2235                 if ((error = copyout(&ctl, uap->ctl, sizeof(ctl))) != 0)
 2236                         return error;
 2237         }
 2238 
 2239         if (uap->dat) {
 2240                 if ((error = copyout(&dat, uap->dat, sizeof(dat))) != 0)
 2241                         return error;
 2242         }
 2243 
 2244         if (uap->flags) { /* XXX: Need translation */
 2245                 if ((error = copyout(&fl, uap->flags, sizeof(fl))) != 0)
 2246                         return error;
 2247         }
 2248 
 2249         *retval = 0;
 2250 
 2251 #ifdef DEBUG_SVR4
 2252         show_msg("<getmsg", uap->fd, uap->ctl,
 2253                  uap->dat, fl);
 2254 #endif /* DEBUG_SVR4 */
 2255         return error;
 2256 }
 2257 
 2258 int svr4_sys_send(td, uap)
 2259         struct thread *td;
 2260         struct svr4_sys_send_args *uap;
 2261 {
 2262         struct osend_args osa;
 2263         osa.s = uap->s;
 2264         osa.buf = uap->buf;
 2265         osa.len = uap->len;
 2266         osa.flags = uap->flags;
 2267         return osend(td, &osa);
 2268 }
 2269 
 2270 int svr4_sys_recv(td, uap)
 2271         struct thread *td;
 2272         struct svr4_sys_recv_args *uap;
 2273 {
 2274         struct orecv_args ora;
 2275         ora.s = uap->s;
 2276         ora.buf = uap->buf;
 2277         ora.len = uap->len;
 2278         ora.flags = uap->flags;
 2279         return orecv(td, &ora);
 2280 }
 2281 
 2282 /* 
 2283  * XXX This isn't necessary, but it's handy for inserting debug code into
 2284  * sendto().  Let's leave it here for now...
 2285  */     
 2286 int
 2287 svr4_sys_sendto(td, uap)
 2288         struct thread *td;
 2289         struct svr4_sys_sendto_args *uap;
 2290 {
 2291         struct sendto_args sa;
 2292 
 2293         sa.s = uap->s;
 2294         sa.buf = uap->buf;
 2295         sa.len = uap->len;
 2296         sa.flags = uap->flags;
 2297         sa.to = (caddr_t)uap->to;
 2298         sa.tolen = uap->tolen;
 2299 
 2300         DPRINTF(("calling sendto()\n"));
 2301         return sendto(td, &sa);
 2302 }
 2303 

Cache object: 29a4c67982ccf6df4dceb97c366831a2


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