]> git.sesse.net Git - rdpsrv/blobdiff - Xserver/lib/xtrans/Xtransmnx.c
Import X server from vnc-3.3.7.
[rdpsrv] / Xserver / lib / xtrans / Xtransmnx.c
diff --git a/Xserver/lib/xtrans/Xtransmnx.c b/Xserver/lib/xtrans/Xtransmnx.c
new file mode 100644 (file)
index 0000000..9e5b5e6
--- /dev/null
@@ -0,0 +1,1639 @@
+/* $XFree86: xc/lib/xtrans/Xtransmnx.c,v 3.3 1996/05/10 06:55:50 dawes Exp $ */
+
+/*
+Xtransmnx.c
+
+Created:       11 April 1994 by Philip Homburg <philip@cs.vu.nl>
+*/
+
+
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/nbio.h>
+#include <net/hton.h>
+#include <net/netlib.h>
+#include <net/gen/in.h>
+#include <net/gen/netdb.h>
+#include <net/gen/tcp.h>
+#include <net/gen/tcp_io.h>
+
+struct private
+{
+       int nonblocking;
+
+       int read_inprogress;
+       char *read_buffer;
+       size_t read_bufsize;
+       size_t read_size;
+       size_t read_offset;
+
+       int write_inprogress;
+       char *write_buffer;
+       size_t write_bufsize;
+       size_t write_size;
+       size_t write_offset;
+       int write_errno;
+
+       int listen_completed;
+       u16_t listen_port;
+       XtransConnInfo listen_list;
+};
+#define RD_BUFSIZE     1024
+#define WR_BUFSIZE     1024
+
+static XtransConnInfo listen_list= NULL;
+
+static XtransConnInfo alloc_ConnInfo(Xtransport *thistrans);
+static void free_ConnInfo(XtransConnInfo ciptr);
+static struct private *alloc_private(size_t rd_size, size_t wr_size);
+static void free_private(struct private *priv);
+static void read_cb(nbio_ref_t ref, int res, int err);
+static void write_cb(nbio_ref_t ref, int res, int err);
+static void listen_cb(nbio_ref_t ref, int res, int err);
+static int restart_listen(XtransConnInfo ciptr);
+
+#ifdef TRANS_CLIENT
+static XtransConnInfo
+TRANS(MnxTcpOpenCOTSClient) (thistrans, protocol, host, port)
+
+Xtransport *thistrans;
+char      *protocol;
+char      *host;
+char       *port;
+
+{
+       XtransConnInfo  ciptr;
+       char *tcp_device;
+       int s_errno;
+       int fd;
+       nbio_ref_t ref;
+
+
+       PRMSG(2, "MnxTcpOpenCOTSClient(%s,%s,%s)\n",
+               protocol, host, port);
+
+       if ((ciptr= alloc_ConnInfo(thistrans)) == NULL)
+       {
+               PRMSG(1,
+                       "MnxTcpOpenCOTSClient: alloc_ConnInfo failed\n",
+                       0, 0, 0);
+               return NULL;
+       }
+       if ((ciptr->priv= (char *)alloc_private(RD_BUFSIZE, WR_BUFSIZE)) ==
+               NULL)
+       {
+               PRMSG(1,
+                       "MnxTcpOpenCOTSClient: alloc_private() failed\n",
+                       0, 0, 0);
+               s_errno= errno;
+               free_ConnInfo(ciptr);
+               errno= s_errno;
+               return NULL;
+       }
+
+       if ((tcp_device= getenv("TCP_DEVICE")) == NULL)
+               tcp_device= TCP_DEVICE;
+       PRMSG(4, "MnxTcpOpenCOTSClient: tcp_device= '%s'\n",
+               tcp_device, 0, 0);
+
+       if ((fd= open(tcp_device, O_RDWR)) == -1)
+       {
+               PRMSG(1,
+                       "MnxTcpOpenCOTSClient: open '%s' failed: %s\n",
+                       tcp_device, strerror(errno), 0);
+               s_errno= errno;
+               free_ConnInfo(ciptr);
+               errno= s_errno;
+               return NULL;
+       }
+       ciptr->fd= fd;
+       ref.ref_ptr= ciptr;
+       nbio_register(fd);
+       nbio_setcallback(fd, ASIO_READ, read_cb, ref);
+       nbio_setcallback(fd, ASIO_WRITE, write_cb, ref);
+       return ciptr;
+}
+#endif /* TRANS_CLIENT */
+
+#ifdef TRANS_SERVER
+static XtransConnInfo
+TRANS(MnxTcpOpenCOTSServer) (thistrans, protocol, host, port)
+
+Xtransport *thistrans;
+char      *protocol;
+char      *host;
+char      *port;
+
+{
+       XtransConnInfo  ciptr;
+       char *tcp_device;
+       int s_errno;
+       int fd;
+       nbio_ref_t ref;
+
+
+       PRMSG(2, "MnxTcpOpenCOTSServer(%s,%s,%s)\n",
+               protocol, host, port);
+
+       if ((ciptr= alloc_ConnInfo(thistrans)) == NULL)
+       {
+               PRMSG(1,
+                       "MnxTcpOpenCOTSServer: alloc_ConnInfo failed\n",
+                       0, 0, 0);
+               return NULL;
+       }
+       if ((ciptr->priv= (char *)alloc_private(RD_BUFSIZE, WR_BUFSIZE)) ==
+               NULL)
+       {
+               PRMSG(1,
+                       "MnxTcpOpenCOTSServer: alloc_private() failed\n",
+                       0, 0, 0);
+               s_errno= errno;
+               free_ConnInfo(ciptr);
+               errno= s_errno;
+               return NULL;
+       }
+
+       if ((tcp_device= getenv("TCP_DEVICE")) == NULL)
+               tcp_device= TCP_DEVICE;
+       PRMSG(4, "MnxTcpOpenCOTSServer: tcp_device= '%s'\n",
+               tcp_device, 0, 0);
+
+       if ((fd= open(tcp_device, O_RDWR)) == -1)
+       {
+               PRMSG(1,
+                       "MnxTcpOpenCOTSServer: open '%s' failed: %s\n",
+                       tcp_device, strerror(errno), 0);
+               s_errno= errno;
+               free_ConnInfo(ciptr);
+               errno= s_errno;
+               return NULL;
+       }
+       PRMSG(5, "MnxTcpOpenCOTSServer: fd= '%d'\n", fd, 0, 0);
+       ciptr->fd= fd;
+       ref.ref_ptr= ciptr;
+       nbio_register(fd);
+       nbio_setcallback(fd, ASIO_IOCTL, listen_cb, ref);
+       return ciptr;
+}
+#endif /* TRANS_SERVER */
+
+#ifdef TRANS_CLIENT
+static XtransConnInfo
+TRANS(MnxTcpOpenCLTSClient) (thistrans, protocol, host, port)
+
+Xtransport *thistrans;
+char      *protocol;
+char      *host;
+char      *port;
+
+{
+       abort();
+}
+#endif /* TRANS_CLIENT */
+
+#ifdef TRANS_SERVER
+static XtransConnInfo
+TRANS(MnxTcpOpenCLTSServer) (thistrans, protocol, host, port)
+
+Xtransport *thistrans;
+char      *protocol;
+char      *host;
+char      *port;
+
+{
+       abort();
+}
+#endif /* TRANS_SERVER */
+
+#ifdef TRANS_REOPEN
+
+static XtransConnInfo
+TRANS(MnxTcpReopenCOTSServer) (thistrans, fd, port)
+
+Xtransport *thistrans;
+int       fd;
+char      *port;
+
+{
+    XtransConnInfo     ciptr;
+    int                        i;
+
+    PRMSG (2,
+       "MnxTcpReopenCOTSServer(%d, %s)\n", fd, port, 0);
+
+    abort();
+}
+
+static XtransConnInfo
+TRANS(MnxTcpReopenCLTSServer) (thistrans, fd, port)
+
+Xtransport *thistrans;
+int       fd;
+char      *port;
+
+{
+    XtransConnInfo     ciptr;
+    int                        i;
+
+
+    PRMSG (2,
+       "MnxTcpReopenCLTSServer(%d, %s)\n", fd, port, 0);
+
+    abort();
+}
+
+#endif /* TRANS_REOPEN */
+
+
+
+static int
+TRANS(MnxTcpSetOption) (ciptr, option, arg)
+
+XtransConnInfo         ciptr;
+int            option;
+int            arg;
+
+{
+       int flags;
+       struct private *priv;
+
+       PRMSG(2, "MnxTcpSetOption(%d,%d,%d)\n",
+               ciptr->fd, option, arg);
+
+       priv= (struct private *)ciptr->priv;
+       switch(option)
+       {
+       case TRANS_NONBLOCKING:
+               flags= fcntl(ciptr->fd, F_GETFD);
+               if (flags == -1)
+               {
+                       PRMSG(1,
+                       "MnxTcpSetOption: fcntl F_GETFD failed: %s\n",
+                               strerror(errno), 0, 0);
+                       return -1;
+               }
+               if (arg == 0)
+                       flags &= ~FD_ASYNCHIO;
+               else if (arg == 1)
+                       flags |= FD_ASYNCHIO;
+               else
+               {
+                       PRMSG(1,
+               "MnxTcpSetOption: bad arg for TRANS_NONBLOCKING: %d\n",
+                               arg, 0, 0);
+                       return -1;
+               }
+               if (fcntl(ciptr->fd, F_SETFD, flags) == -1)
+               {
+                       PRMSG(1,
+                       "MnxTcpSetOption: fcntl F_SETFD failed: %s\n",
+                               strerror(errno), 0, 0);
+                       return -1;
+               }
+               priv->nonblocking= arg;
+               return 0;
+       case TRANS_CLOSEONEXEC:
+               flags= fcntl(ciptr->fd, F_GETFD);
+               if (flags == -1)
+               {
+                       PRMSG(1,
+                       "MnxTcpSetOption: fcntl F_GETFD failed: %s\n",
+                               strerror(errno), 0, 0);
+                       return -1;
+               }
+               if (arg == 0)
+                       flags &= ~FD_CLOEXEC;
+               else if (arg == 1)
+                       flags |= FD_CLOEXEC;
+               else
+               {
+                       PRMSG(1,
+               "MnxTcpSetOption: bad arg for TRANS_CLOSEONEXEC: %d\n",
+                               arg, 0, 0);
+                       return -1;
+               }
+               if (fcntl(ciptr->fd, F_SETFD, flags) == -1)
+               {
+                       PRMSG(1,
+                       "MnxTcpSetOption: fcntl F_SETFD failed: %s\n",
+                               strerror(errno), 0, 0);
+                       return -1;
+               }
+               return 0;
+       default:
+               PRMSG(1, "MnxTcpSetOption: unknown option '%d'\n",
+                       option, 0, 0);
+               errno= EINVAL;
+               return -1;
+       }
+}
+
+
+#ifdef TRANS_SERVER
+static int
+TRANS(MnxTcpCreateListener) (ciptr, port)
+
+XtransConnInfo ciptr;
+char           *port;
+
+{
+       struct servent *servp;
+       tcpport_t num_port;
+       char *check;
+       nwio_tcpconf_t tcpconf;
+       nwio_tcpcl_t tcpcl;
+       int r, s_errno, flags;
+       struct private *priv;
+       struct sockaddr_in *addr;
+
+       PRMSG(2, "MnxTcpCreateListener(%d,%s)\n", ciptr->fd, port, 0);
+
+       priv= (struct private *)ciptr->priv;
+
+       if (port == NULL)
+               num_port= 0;
+       else
+       {
+               num_port= strtol(port, &check, 10);
+               num_port= htons(num_port);
+               if (check[0] == '\0')
+                       port= NULL;
+       }
+
+#ifdef X11_t
+       /*
+        * X has a well known port, that is transport dependent. It is easier
+        * to handle it here, than try and come up with a transport independent
+        * representation that can be passed in and resolved the usual way.
+        *
+        * The port that is passed here is really a string containing the
+        * idisplay from ConnectDisplay().
+        */
+       if (port == NULL)
+               num_port= htons(ntohs(num_port) + X_TCP_PORT);
+#endif
+       if (port != NULL)
+       {
+               if ((servp = getservbyname (port, "tcp")) == NULL)
+               {
+                       PRMSG(1,
+               "MnxTcpCreateListener: can't get service for %s\n",
+                               port, 0, 0);
+                       errno= EINVAL;
+                       return TRANS_CREATE_LISTENER_FAILED;
+               }
+               num_port= servp->s_port;
+       }
+
+       tcpconf.nwtc_flags= NWTC_SHARED | NWTC_UNSET_RA | NWTC_UNSET_RP;
+       if (num_port != 0)
+       {
+               tcpconf.nwtc_locport= num_port;
+               tcpconf.nwtc_flags |= NWTC_LP_SET;
+       }
+       else
+               tcpconf.nwtc_flags |= NWTC_LP_SEL;
+
+       if (ioctl(ciptr->fd, NWIOSTCPCONF, &tcpconf) == -1)
+       {
+               PRMSG(1,
+               "MnxTcpCreateListener: NWIOSTCPCONF failed: %s\n",
+                       strerror(errno),0, 0);
+               return TRANS_CREATE_LISTENER_FAILED;
+       }
+
+       if (ioctl(ciptr->fd, NWIOGTCPCONF, &tcpconf) == -1)
+       {
+               PRMSG(1,
+               "MnxTcpListen: NWIOGTCPCONF failed: %s\n",
+                       strerror(errno),0, 0);
+               return TRANS_CREATE_LISTENER_FAILED;
+       }
+
+       priv->listen_port= tcpconf.nwtc_locport;
+
+       if ((addr= (struct sockaddr_in *)xalloc(sizeof(struct sockaddr_in)))
+               == NULL)
+       {
+               PRMSG(1, "MnxTcpAccept: malloc failed\n", 0, 0, 0);
+               return TRANS_CREATE_LISTENER_FAILED;
+       }
+       addr->sin_family= AF_INET;
+       addr->sin_addr.s_addr= tcpconf.nwtc_locaddr;
+       addr->sin_port= tcpconf.nwtc_locport;
+       if (ciptr->addr)
+               xfree(ciptr->addr);
+       ciptr->addr= (char *)addr;
+       ciptr->addrlen= sizeof(struct sockaddr_in);
+
+       flags= fcntl(ciptr->fd, F_GETFD);
+       if (flags == -1)
+       {
+               PRMSG(1,
+               "MnxTcpCreateListener: fcntl F_GETFD failed: %s\n",
+                       strerror(errno), 0, 0);
+               return TRANS_CREATE_LISTENER_FAILED;
+       }
+       if (fcntl(ciptr->fd, F_SETFD, flags | FD_ASYNCHIO) == -1)
+       {
+               PRMSG(1,
+               "MnxTcpCreateListener: fcntl F_SETFD failed: %s\n",
+                       strerror(errno), 0, 0);
+               return TRANS_CREATE_LISTENER_FAILED;
+       }
+
+       tcpcl.nwtcl_flags= 0;
+       r= ioctl(ciptr->fd, NWIOTCPLISTEN, &tcpcl);
+       s_errno= errno;
+
+       if (fcntl(ciptr->fd, F_SETFD, flags) == -1)
+       {
+               PRMSG(1,
+               "MnxTcpCreateListener: fcntl F_SETFD failed: %s\n",
+                       strerror(errno), 0, 0);
+               return TRANS_CREATE_LISTENER_FAILED;
+       }
+
+       if (r == -1 && s_errno == EINPROGRESS)
+       {
+               nbio_inprogress(ciptr->fd, ASIO_IOCTL, 1 /* read */,
+                       1 /* write */, 0 /* exception */);
+               return 0;
+       }
+       if (r == 0)
+       {
+               priv->listen_completed= 1;
+               return 0;
+       }
+
+       errno= s_errno;
+       PRMSG(1, "MnxTcpCreateListener: NWIOTCPLISTEN failed: %s\n",
+               strerror(errno), 0, 0);
+       return TRANS_CREATE_LISTENER_FAILED;
+}
+#endif /* TRANS_SERVER */
+
+
+#ifdef TRANS_SERVER
+static int
+TRANS(MnxTcpResetListener) (ciptr)
+
+XtransConnInfo ciptr;
+{
+       PRMSG(2, "MnxTcpResetListener(%d)\n", ciptr->fd, 0, 0);
+       return TRANS_RESET_NOOP;
+}
+#endif /* TRANS_SERVER */
+
+#ifdef TRANS_SERVER
+static XtransConnInfo
+TRANS(MnxTcpAccept) (ciptr_listen, status)
+
+XtransConnInfo ciptr_listen;
+int           *status;
+
+{
+       XtransConnInfo  ciptr;
+       int s_errno;
+       int fd;
+       nbio_ref_t ref;
+       struct private *priv;
+       nwio_tcpconf_t tcpconf;
+       struct sockaddr_in *addr;
+
+       PRMSG(2, "MnxTcpAccept(%d,%p)\n", ciptr_listen->fd, status, 0);
+
+       priv= (struct private *)ciptr_listen->priv;
+       *status= TRANS_ACCEPT_MISC_ERROR;
+
+       if (!priv->listen_completed)
+       {
+               PRMSG(1, "MnxTcpAccept: listen is not completed\n",
+                       0, 0, 0);
+               *status= TRANS_ACCEPT_FAILED;
+               return NULL;
+       }
+       priv->listen_completed= 0;
+
+       if ((ciptr= alloc_ConnInfo(ciptr_listen->transptr)) == NULL)
+       {
+               PRMSG(1,
+                       "MnxTcpAccept: alloc_ConnInfo failed\n",
+                       0, 0, 0);
+               *status= TRANS_ACCEPT_BAD_MALLOC;
+               return NULL;
+       }
+       if ((ciptr->priv= (char *)alloc_private(RD_BUFSIZE, WR_BUFSIZE)) ==
+               NULL)
+       {
+               PRMSG(1,
+                       "MnxTcpAccept: alloc_private() failed\n",
+                       0, 0, 0);
+               s_errno= errno;
+               free_ConnInfo(ciptr);
+               errno= s_errno;
+               *status= TRANS_ACCEPT_BAD_MALLOC;
+               return NULL;
+       }
+
+       fd= dup(ciptr_listen->fd);
+       if (fd == -1)
+       {
+               s_errno= errno;
+               PRMSG(1, "MnxTcpAccept: dup failed: %s\n",
+                       strerror(errno), 0, 0);
+               free_ConnInfo(ciptr);
+               *status= TRANS_ACCEPT_FAILED;
+               return NULL;
+       }
+       if (restart_listen(ciptr_listen) == -1)
+       {
+               priv->listen_list= listen_list;
+               listen_list= ciptr_listen;
+               PRMSG(1, "MnxTcpAccept: unable to restart listen\n",
+                       0, 0, 0);
+       }
+       ciptr->fd= fd;
+       ref.ref_ptr= ciptr;
+       nbio_register(fd);
+       nbio_setcallback(fd, ASIO_WRITE, write_cb, ref);
+       nbio_setcallback(fd, ASIO_READ, read_cb, ref);
+
+       if (ioctl(ciptr->fd, NWIOGTCPCONF, &tcpconf) == -1)
+       {
+               PRMSG(1, "MnxTcpAccept: NWIOGTCPCONF failed: %s\n",
+                       strerror(errno),0, 0);
+               close(fd);
+               free_ConnInfo(ciptr);
+               *status= TRANS_ACCEPT_MISC_ERROR;
+               return NULL;
+       }
+       if ((addr= (struct sockaddr_in *)xalloc(sizeof(struct sockaddr_in)))
+               == NULL)
+       {
+               PRMSG(1, "MnxTcpAccept: malloc failed\n", 0, 0, 0);
+               close(fd);
+               free_ConnInfo(ciptr);
+               *status= TRANS_ACCEPT_BAD_MALLOC;
+               return NULL;
+       }
+       addr->sin_family= AF_INET;
+       addr->sin_addr.s_addr= tcpconf.nwtc_locaddr;
+       addr->sin_port= tcpconf.nwtc_locport;
+       if (ciptr->addr)
+               xfree(ciptr->addr);
+       ciptr->addr= (char *)addr;
+       ciptr->addrlen= sizeof(struct sockaddr_in);
+       if (*(u8_t *)&tcpconf.nwtc_remaddr == 127)
+       {
+               /* Make ConvertAddress return FamilyLocal */
+               addr->sin_addr.s_addr= tcpconf.nwtc_remaddr;
+       }
+
+       if ((addr= (struct sockaddr_in *)xalloc(sizeof(struct sockaddr_in)))
+               == NULL)
+       {
+               PRMSG(1, "MnxTcpConnect: malloc failed\n", 0, 0, 0);
+               close(fd);
+               free_ConnInfo(ciptr);
+               *status= TRANS_ACCEPT_BAD_MALLOC;
+               return NULL;
+       }
+       addr->sin_family= AF_INET;
+       addr->sin_addr.s_addr= tcpconf.nwtc_remaddr;
+       addr->sin_port= tcpconf.nwtc_remport;
+       ciptr->peeraddr= (char *)addr;
+       ciptr->peeraddrlen= sizeof(struct sockaddr_in);
+       *status= 0;
+       return ciptr;
+}
+#endif /* TRANS_SERVER */
+
+TRANS(MnxTcpConnect) (ciptr, host, port)
+
+XtransConnInfo         ciptr;
+char           *host;
+char           *port;
+
+{
+       struct hostent *hostp;
+       struct servent *servp;
+       char hostnamebuf[256];          /* tmp space */
+       tcpport_t num_port;
+       ipaddr_t num_addr;
+       char *check;
+       nwio_tcpconf_t tcpconf;
+       nwio_tcpcl_t tcpcl;
+       struct sockaddr_in *addr;
+
+       PRMSG(2, "MnxTcpConnect(%d,%s,%s)\n", ciptr->fd, host, port);
+
+       if (!host)
+       {
+               hostnamebuf[0] = '\0';
+               (void) TRANS(GetHostname) (hostnamebuf, sizeof hostnamebuf);
+               host = hostnamebuf;
+       }
+
+
+       num_port= strtol(port, &check, 10);
+       num_port= htons(num_port);
+       if (check[0] == '\0')
+               port= NULL;
+#ifdef X11_t
+       /*
+        * X has a well known port, that is transport dependent. It is easier
+        * to handle it here, than try and come up with a transport independent
+        * representation that can be passed in and resolved the usual way.
+        *
+        * The port that is passed here is really a string containing the
+        * idisplay from ConnectDisplay().
+        */
+       if (port == NULL)
+               num_port= htons(ntohs(num_port) + X_TCP_PORT);
+#endif
+
+       num_addr= inet_addr(host);
+       if (num_addr != -1)
+               host= NULL;
+
+       if (host != NULL)
+       {
+               if ((hostp = gethostbyname(host)) == NULL)
+               {
+                       PRMSG(1,
+                       "MnxTcpConnect: can't get address for %s\n",
+                               host, 0, 0);
+                       errno= EINVAL;
+                       return TRANS_CONNECT_FAILED;
+               }
+               if (hostp->h_addrtype != AF_INET)  /* is IP host? */
+               {
+                   PRMSG(1, "MnxTcpConnect: %s in not an INET host\n",
+                         host, 0, 0);
+                   errno= EINVAL;
+                   return TRANS_CONNECT_FAILED;
+               }
+               num_addr= *(ipaddr_t *)hostp->h_addr;
+       }
+
+       if (port != NULL)
+       {
+               if ((servp = getservbyname (port, "tcp")) == NULL)
+               {
+                       PRMSG(1,
+                       "MnxTcpConnect: can't get service for %s\n",
+                               port, 0, 0);
+                       errno= EINVAL;
+                       return TRANS_CONNECT_FAILED;
+               }
+               num_port= servp->s_port;
+       }
+
+       tcpconf.nwtc_flags= NWTC_EXCL | NWTC_LP_SEL | NWTC_SET_RA |
+               NWTC_SET_RP;
+       tcpconf.nwtc_remaddr= num_addr;
+       tcpconf.nwtc_remport= num_port;
+       if (ioctl(ciptr->fd, NWIOSTCPCONF, &tcpconf) == -1)
+       {
+               PRMSG(1, "MnxTcpConnect: NWIOSTCPCONF failed: %s\n",
+                       strerror(errno),0, 0);
+               return TRANS_CONNECT_FAILED;
+       }
+
+       tcpcl.nwtcl_flags= 0;
+       if (ioctl(ciptr->fd, NWIOTCPCONN, &tcpcl) == -1)
+       {
+               PRMSG(1, "MnxTcpConnect: connect failed: %s\n",
+                       strerror(errno),0, 0);
+               if (errno == ECONNREFUSED || errno == EINTR)
+                       return TRANS_TRY_CONNECT_AGAIN;
+               else
+                       return TRANS_CONNECT_FAILED;
+       }
+
+       if (ioctl(ciptr->fd, NWIOGTCPCONF, &tcpconf) == -1)
+       {
+               PRMSG(1, "MnxTcpConnect: NWIOGTCPCONF failed: %s\n",
+                       strerror(errno),0, 0);
+               return TRANS_CONNECT_FAILED;
+       }
+       if ((addr= (struct sockaddr_in *)xalloc(sizeof(struct sockaddr_in)))
+               == NULL)
+       {
+               PRMSG(1, "MnxTcpConnect: malloc failed\n", 0, 0, 0);
+               return TRANS_CONNECT_FAILED;
+       }
+       addr->sin_family= AF_INET;
+       addr->sin_addr.s_addr= tcpconf.nwtc_locaddr;
+       addr->sin_port= tcpconf.nwtc_locport;
+       ciptr->addr= (char *)addr;
+       ciptr->addrlen= sizeof(struct sockaddr_in);
+       if (*(u8_t *)&tcpconf.nwtc_remaddr == 127)
+       {
+               /* Make ConvertAddress return FamilyLocal */
+               addr->sin_addr.s_addr= tcpconf.nwtc_remaddr;
+       }
+
+       if ((addr= (struct sockaddr_in *)xalloc(sizeof(struct sockaddr_in)))
+               == NULL)
+       {
+               PRMSG(1, "MnxTcpConnect: malloc failed\n", 0, 0, 0);
+               return TRANS_CONNECT_FAILED;
+       }
+       addr->sin_family= AF_INET;
+       addr->sin_addr.s_addr= tcpconf.nwtc_remaddr;
+       addr->sin_port= tcpconf.nwtc_remport;
+       ciptr->peeraddr= (char *)addr;
+       ciptr->peeraddrlen= sizeof(struct sockaddr_in);
+
+       return 0;
+}
+
+static int
+TRANS(MnxTcpBytesReadable) (ciptr, pend)
+
+XtransConnInfo ciptr;
+BytesReadable_t *pend;
+
+{
+       struct private *priv;
+       int r;
+
+       PRMSG(2, "MnxTcpBytesReadable(%x,%d,%x)\n",
+               ciptr, ciptr->fd, pend);
+
+       *pend= 0;
+
+       priv= (struct private *)ciptr->priv;
+       if (priv->read_inprogress)
+       {
+               PRMSG(5, "MnxTcpBytesReadable: read inprogress, %d\n",
+                       *pend, 0, 0);
+               return *pend;
+       }
+       if (priv->read_offset < priv->read_size)
+       {
+               *pend= priv->read_size-priv->read_offset;
+               PRMSG(5, "MnxTcpBytesReadable: %d\n",
+                       *pend, 0, 0);
+               return *pend;
+       }
+       priv->read_offset= 0;
+       r= read(ciptr->fd, priv->read_buffer, priv->read_bufsize);
+       if (r >= 0)
+       {
+               if (r == 0)
+                       r= 1;   /* Signal EOF condition */
+
+               priv->read_size= r;
+               PRMSG(5, "MnxTcpBytesReadable: %d\n",
+                       *pend, 0, 0);
+               *pend= r;
+       }
+       else if (r == -1 && errno == EINPROGRESS)
+       {
+               priv->read_inprogress= 1;
+               nbio_inprogress(ciptr->fd, ASIO_READ, 1 /* read */,
+                       0 /* write */, 0 /* exception */);
+       }
+       else
+       {
+               PRMSG(1, "MnxTcpBytesReadable: read failed: %s\n",
+                       strerror(errno), 0, 0);
+               return -1;
+       }
+       PRMSG(5, "MnxTcpBytesReadable: %d\n", *pend, 0, 0);
+       return *pend;
+}
+
+
+static int
+TRANS(MnxTcpRead) (ciptr, buf, size)
+
+XtransConnInfo ciptr;
+char           *buf;
+int            size;
+
+{
+       int len, r, ret, s_errno;
+       int offset;
+       struct private *priv;
+       asio_fd_set_t fd_set;
+       fwait_t fw;
+
+       PRMSG(2, "MnxTcpRead(%d,%x,%d)\n", ciptr->fd, buf, size);
+
+       priv= (struct private *)ciptr->priv;
+       offset= 0;
+
+       if (priv->read_inprogress)
+       {
+               PRMSG(5, "MnxTcpRead: EAGAIN\n", 0, 0, 0);
+               errno= EAGAIN;
+               return -1;
+       }
+
+       /* Copy any data left in the buffer */
+       if (priv->read_offset < priv->read_size)
+       {
+               len= priv->read_size-priv->read_offset;
+               if (len > size-offset)
+                       len= size-offset;
+               PRMSG(5, "MnxTcpRead: copying %d bytes\n", len, 0, 0);
+
+               memcpy(buf+offset, priv->read_buffer + priv->read_offset,
+                       len);
+               offset += len;
+               priv->read_offset += len;
+               if (priv->read_offset < priv->read_size)
+                       return offset;
+       }
+
+       /* Try to read directly into the user's buffer. */
+       ret= 0;
+       s_errno= 0;
+       while(offset < size)
+       {
+               r= read(ciptr->fd, buf+offset, size-offset);
+               if (r == -1 && errno == EINPROGRESS)
+               {
+                       r= fcancel(ciptr->fd, ASIO_READ);
+                       if (r == -1)
+                               abort();
+                       ASIO_FD_ZERO(&fd_set);
+                       ASIO_FD_SET(ciptr->fd, ASIO_READ, &fd_set);
+                       fw.fw_flags= FWF_NONBLOCK;
+                       fw.fw_bits= fd_set.afds_bits;
+                       fw.fw_maxfd= ASIO_FD_SETSIZE;
+                       r= fwait(&fw);
+                       if (r == -1 || fw.fw_fd != ciptr->fd ||
+                               fw.fw_operation != ASIO_READ)
+                       {
+                               abort();
+                       }
+                       r= fw.fw_result;
+                       errno= fw.fw_errno;
+               }
+
+               if (r > 0)
+               {
+                       PRMSG(5, "MnxTcpRead: read %d bytes\n", r,
+                               0, 0);
+                       offset += r;
+                       continue;
+               }
+               else if (r == 0)
+               {
+                       PRMSG(5, "MnxTcpRead: read EOF\n", 0, 0, 0);
+                       break;
+               }
+               else
+               {
+                       if (errno == EINTR)
+                       {
+                               PRMSG(5, "MnxTcpRead: EINTR\n",
+                                       0, 0, 0);
+                               errno= EAGAIN;
+                       }
+                       else
+                       {
+                               PRMSG(1, "MnxTcpRead: read error %s\n",
+                                       strerror(errno), 0, 0);
+                       }
+                       s_errno= errno;
+                       ret= -1;
+                       break;
+               }
+       }
+       if (offset != 0)
+               ret= offset;
+
+       if (priv->read_offset != priv->read_size)
+               abort();
+       priv->read_offset= 0;
+       priv->read_size= 0;
+       if (priv->nonblocking)
+       {
+               r= read(ciptr->fd, priv->read_buffer, priv->read_bufsize);
+               if (r >= 0)
+               {
+                       PRMSG(5, "MnxTcpRead: buffered %d bytes\n",
+                               r, 0, 0);
+                       priv->read_size= r;
+               }
+               else if (r == -1 && errno == EINPROGRESS)
+               {
+                       priv->read_inprogress= 1;
+                       nbio_inprogress(ciptr->fd, ASIO_READ, 1 /* read */,
+                               0 /* write */, 0 /* exception */);
+               }
+               else
+               {
+                       PRMSG(1, "MnxTcpRead: read failed: %s\n",
+                               strerror(errno), 0, 0);
+               }
+       }
+       errno= s_errno;
+       return ret;
+}
+
+
+static int
+TRANS(MnxTcpWrite) (ciptr, buf, size)
+
+XtransConnInfo ciptr;
+char          *buf;
+int           size;
+
+{
+       int len, r, ret, s_errno;
+       int offset;
+       struct private *priv;
+       asio_fd_set_t fd_set;
+       fwait_t fw;
+
+       PRMSG(2, "MnxTcpWrite(%d,%x,%d)\n", ciptr->fd, buf, size);
+
+       priv= (struct private *)ciptr->priv;
+       offset= 0;
+
+       if (priv->write_errno)
+       {
+               PRMSG(5, "MnxTcpWrite: write_errno %d\n",
+                       priv->write_errno, 0, 0);
+               errno= priv->write_errno;
+               return -1;
+       }
+
+       if (priv->write_inprogress)
+       {
+               PRMSG(5, "MnxTcpWrite: EAGAIN\n", 0, 0, 0);
+               errno= EAGAIN;
+               return -1;
+       }
+
+       /* Try to write directly out of the user's buffer. */
+       ret= 0;
+       s_errno= 0;
+       while(offset < size)
+       {
+               r= write(ciptr->fd, buf+offset, size-offset);
+               if (r == -1 && errno == EINPROGRESS)
+               {
+                       r= fcancel(ciptr->fd, ASIO_WRITE);
+                       if (r == -1)
+                               abort();
+                       ASIO_FD_ZERO(&fd_set);
+                       ASIO_FD_SET(ciptr->fd, ASIO_WRITE, &fd_set);
+                       fw.fw_flags= FWF_NONBLOCK;
+                       fw.fw_bits= fd_set.afds_bits;
+                       fw.fw_maxfd= ASIO_FD_SETSIZE;
+                       r= fwait(&fw);
+                       if (r == -1 || fw.fw_fd != ciptr->fd ||
+                               fw.fw_operation != ASIO_WRITE)
+                       {
+                               abort();
+                       }
+                       r= fw.fw_result;
+                       errno= fw.fw_errno;
+               }
+               if (r > 0)
+               {
+                       PRMSG(5, "MnxTcpWrite: wrote %d bytes\n", r,
+                               0, 0);
+                       offset += r;
+                       continue;
+               }
+               else if (r == 0)
+                       abort();
+               else
+               {
+                       if (errno == EINTR)
+                       {
+                               PRMSG(5, "MnxTcpWrite: EINTR\n",
+                                       0, 0, 0);
+                               errno= EAGAIN;
+                       }
+                       else
+                       {
+                               PRMSG(1,
+                               "MnxTcpWrite: write error: %s\n",
+                                       strerror(errno), 0, 0);
+                       }
+                       s_errno= errno;
+                       ret= -1;
+                       break;
+               }
+       }
+
+       /* Copy any data to the buffer */
+       if (offset < size)
+       {
+               len= priv->write_bufsize;
+               if (len > size-offset)
+                       len= size-offset;
+               PRMSG(5, "MnxTcpWrite: copying %d bytes\n", len, 0, 0);
+
+               memcpy(priv->write_buffer, buf+offset, len);
+               offset += len;
+               priv->write_offset= 0;
+               priv->write_size= len;
+       }
+       if (offset != 0)
+               ret= offset;
+
+       while (priv->write_offset < priv->write_size)
+       {
+               r= write(ciptr->fd, priv->write_buffer+priv->write_offset,
+                       priv->write_size-priv->write_offset);
+               if (r > 0)
+               {
+                       PRMSG(5, "MnxTcpWrite: wrote %d bytes\n",
+                               r, 0, 0);
+                       priv->write_offset += r;
+                       continue;
+               }
+               else if (r == -1 && errno == EINPROGRESS)
+               {
+                       priv->write_inprogress= 1;
+                       nbio_inprogress(ciptr->fd, ASIO_WRITE, 0 /* read */,
+                               1 /* write */, 0 /* exception */);
+               }
+               else
+               {
+                       PRMSG(1, "MnxTcpWrite: write failed: %s\n",
+                               strerror(errno), 0, 0);
+                       priv->write_errno= errno;
+               }
+               break;
+       }
+
+       errno= s_errno;
+       return ret;
+}
+
+
+static int
+TRANS(MnxTcpReadv) (ciptr, buf, size)
+
+XtransConnInfo ciptr;
+struct iovec   *buf;
+int            size;
+
+{
+       int i, offset, total, len, r;
+
+       PRMSG(2, "MnxTcpReadv(%d,%x,%d)\n", ciptr->fd, buf, size);
+
+       /* Simply call read a number of times. */
+       total= 0;
+       offset= 0;
+       i= 0;
+       while(i<size)
+       {
+               PRMSG(5, "MnxTcpReadv: [%d] size %d-%d\n",
+                       i, buf[i].iov_len, offset);
+               if (offset >= buf[i].iov_len)
+               {
+                       offset= 0;
+                       i++;
+                       continue;
+               }
+               len= buf[i].iov_len-offset;
+               r= TRANS(MnxTcpRead)(ciptr, buf[i].iov_base+offset, len);
+               if (r == -1)
+               {
+                       if (errno == EAGAIN)
+                       {
+                               PRMSG(5,
+                               "MnxTcpReadv: read returned: %s\n",
+                                       strerror(errno), 0, 0);
+                       }
+                       else
+                       {
+                               PRMSG(1,
+                               "MnxTcpReadv: read failed: %s\n",
+                                       strerror(errno), 0, 0);
+                       }
+                       if (total != 0)
+                               return total;
+                       else
+                               return -1;
+               }
+               if (r == 0)
+                       break;
+               if (r > len)
+                       abort();
+               total += r;
+               offset += r;
+       }
+       return total;
+}
+
+static int
+TRANS(MnxTcpWritev) (ciptr, buf, size)
+
+XtransConnInfo         ciptr;
+struct iovec   *buf;
+int            size;
+
+{
+       int i, offset, total, len, r;
+
+       PRMSG(2, "MnxTcpWritev(%d,%x,%d)\n", ciptr->fd, buf, size);
+
+       /* Simply call write a number of times. */
+       total= 0;
+       offset= 0;
+       i= 0;
+       while(i<size)
+       {
+               if (offset >= buf[i].iov_len)
+               {
+                       offset= 0;
+                       i++;
+                       continue;
+               }
+               len= buf[i].iov_len-offset;
+               r= TRANS(MnxTcpWrite)(ciptr, buf[i].iov_base+offset, len);
+               if (r == -1)
+               {
+                       if (errno == EAGAIN)
+                       {
+                               PRMSG(5, "MnxTcpWritev: AGAIN\n",
+                                       0, 0, 0);
+                       }
+                       else
+                       {
+                               PRMSG(1,
+                               "MnxTcpWritev: write failed: %s\n",
+                                       strerror(errno), 0, 0);
+                       }
+                       if (total != 0)
+                               return total;
+                       else
+                               return -1;
+               }
+               if (r == 0 || r > len)
+                       abort();
+               total += r;
+               offset += r;
+       }
+       return total;
+}
+
+
+static int
+TRANS(MnxTcpDisconnect) (ciptr)
+
+XtransConnInfo ciptr;
+
+{
+       PRMSG(2, "MnxTcpDisconnect(%x,%d)\n", ciptr, ciptr->fd, 0);
+
+       return ioctl(ciptr->fd, NWIOTCPSHUTDOWN, NULL);
+}
+
+static int
+TRANS(MnxTcpClose) (ciptr)
+
+XtransConnInfo ciptr;
+
+{
+       XtransConnInfo list, t_ciptr;
+       struct private *priv;
+
+       PRMSG(2, "MnxTcpClose(%x,%d)\n", ciptr, ciptr->fd, 0);
+
+
+       if (listen_list)
+       {
+               list= listen_list;
+               listen_list= NULL;
+               while(list)
+               {
+                       t_ciptr= list;
+                       priv= (struct private *)t_ciptr->priv;
+                       list= priv->listen_list;
+                       if (t_ciptr == ciptr)
+                               continue;
+                       if (restart_listen(t_ciptr) == -1)
+                       {
+                               priv->listen_list= listen_list;
+                               listen_list= t_ciptr;
+                       }
+               }
+       }
+
+       free_private((struct private *)ciptr->priv);
+       nbio_unregister(ciptr->fd);
+       return close (ciptr->fd);
+}
+
+
+static XtransConnInfo
+alloc_ConnInfo(thistrans)
+Xtransport *thistrans;
+{
+       XtransConnInfo ciptr;
+
+       PRMSG(2, " alloc_ConnInfo(%p)\n", thistrans, 0, 0);
+
+       if ((ciptr= (XtransConnInfo) xalloc(sizeof(struct _XtransConnInfo)))
+               == NULL)
+       {
+               PRMSG(1, " alloc_ConnInfo: malloc failed\n", 0, 0, 0);
+               return NULL;
+       }
+       ciptr->transptr= thistrans;
+       ciptr->priv= NULL;
+       ciptr->flags= 0;
+       ciptr->fd= -1;
+       ciptr->port= NULL;
+       ciptr->family= AF_INET;
+       ciptr->addr= NULL;
+       ciptr->addrlen= 0;
+       ciptr->peeraddr= NULL;
+       ciptr->peeraddrlen= 0;
+       return ciptr;
+}
+
+static void
+free_ConnInfo(ciptr)
+XtransConnInfo ciptr;
+{
+       if (ciptr == NULL)
+               return;
+       free_private((struct private *)ciptr->priv);
+       xfree(ciptr);
+}
+
+static struct private *
+alloc_private(rd_size, wr_size)
+size_t rd_size;
+size_t wr_size;
+{
+       struct private *priv;
+       int s_errno;
+       char *buf;
+
+       PRMSG(2, ":alloc_private(%d, %d)\n", rd_size, wr_size, 0);
+
+       if ((priv= (struct private *)xalloc(sizeof(struct private))) == NULL)
+       {
+               PRMSG(1, ":alloc_private: malloc failed\n", 0, 0, 0);
+               return NULL;
+       }
+       priv->nonblocking= 0;
+       priv->read_inprogress= 0;
+       priv->read_buffer= NULL;
+       priv->read_bufsize= rd_size;
+       priv->read_size= 0;
+       priv->read_offset= 0;
+
+       if (rd_size != 0)
+       {
+               if ((buf= xalloc(rd_size)) == NULL)
+               {
+                       PRMSG(1, ":alloc_private: malloc failed\n", 0, 0, 0);
+                       s_errno= errno;
+                       free_private(priv);
+                       errno= s_errno;
+                       return NULL;
+               }
+               priv->read_buffer= buf;
+       }
+
+       priv->write_inprogress= 0;
+       priv->write_buffer= NULL;
+       priv->write_bufsize= rd_size;
+       priv->write_size= 0;
+       priv->write_offset= 0;
+       priv->write_errno= 0;
+
+       if (wr_size != 0)
+       {
+               if ((buf= xalloc(wr_size)) == NULL)
+               {
+                       PRMSG(1, ":alloc_private: malloc failed\n", 0, 0, 0);
+                       s_errno= errno;
+                       free_private(priv);
+                       errno= s_errno;
+                       return NULL;
+               }
+               priv->write_buffer= buf;
+       }
+
+       priv->listen_completed= 0;
+       priv->listen_port= 0;
+       priv->listen_list= NULL;
+
+       return priv;
+}
+
+static void
+free_private(priv)
+struct private *priv;
+{
+       if (priv == NULL)
+               return;
+       xfree(priv->read_buffer);
+       xfree(priv->write_buffer);
+       xfree(priv);
+}
+
+static void
+read_cb(ref, res, err)
+nbio_ref_t ref;
+int res;
+int err;
+{
+       XtransConnInfo ciptr;
+       struct private *priv;
+
+       PRMSG(2, ":read_cb(%x,%d,%d)\n", ref.ref_ptr, res, err);
+
+       ciptr= ref.ref_ptr;
+       priv= (struct private *)ciptr->priv;
+       if (res > 0)
+               priv->read_size= res;
+       priv->read_inprogress= 0;
+}
+
+static void
+write_cb(ref, res, err)
+nbio_ref_t ref;
+int res;
+int err;
+{
+       XtransConnInfo ciptr;
+       struct private *priv;
+       int r;
+
+       PRMSG(2, ":write_cb(%x,%d,%d)\n", ref.ref_ptr, res, err);
+
+       ciptr= ref.ref_ptr;
+       priv= (struct private *)ciptr->priv;
+       if (res > 0)
+               priv->write_offset += res;
+       else if (res == 0)
+               abort();
+       else
+       {
+               priv->write_errno= err;
+               return;
+       }
+       priv->write_inprogress= 0;
+
+       while (priv->write_offset < priv->write_size)
+       {
+               r= write(ciptr->fd, priv->write_buffer+priv->write_offset,
+                       priv->write_size-priv->write_offset);
+               if (r > 0)
+               {
+                       PRMSG(5, "MnxTcpWrite: wrote %d bytes\n",
+                               r, 0, 0);
+                       priv->write_offset += r;
+                       continue;
+               }
+               else if (r == -1 && errno == EINPROGRESS)
+               {
+                       priv->write_inprogress= 1;
+                       nbio_inprogress(ciptr->fd, ASIO_WRITE, 0 /* read */,
+                               1 /* write */, 0 /* exception */);
+               }
+               else
+               {
+                       PRMSG(1, "MnxTcpWrite: write failed: %s\n",
+                               strerror(errno), 0, 0);
+                       priv->write_errno= errno;
+               }
+               break;
+       }
+}
+
+static void
+listen_cb(ref, res, err)
+nbio_ref_t ref;
+int res;
+int err;
+{
+       XtransConnInfo ciptr;
+       struct private *priv;
+       struct sockaddr_in *addr;
+       nwio_tcpconf_t tcpconf;
+
+       PRMSG(2, ":listen_cb(%x,%d,%d)\n", ref.ref_ptr, res, err);
+
+       ciptr= ref.ref_ptr;
+       priv= (struct private *)ciptr->priv;
+       if (res == 0)
+       {
+               if (ioctl(ciptr->fd, NWIOGTCPCONF, &tcpconf) == -1)
+               {
+                       PRMSG(1,
+                       ":listen_cb: NWIOGTCPCONF failed: %s\n",
+                               strerror(errno),0, 0);
+                       return;
+               }
+               if ((addr= (struct sockaddr_in *)xalloc(sizeof(struct sockaddr_in)))
+                       == NULL)
+               {
+                       PRMSG(1, ":listen_cb: malloc failed\n", 0, 0, 0);
+                       return;
+               }
+               addr->sin_family= AF_INET;
+               addr->sin_addr.s_addr= tcpconf.nwtc_locaddr;
+               addr->sin_port= tcpconf.nwtc_locport;
+               if (ciptr->addr)
+                       xfree(ciptr->addr);
+               ciptr->addr= (char *)addr;
+               ciptr->addrlen= sizeof(struct sockaddr_in);
+               priv->listen_completed= 1;
+               return;
+       }
+       PRMSG(2, ":listen_cb: listen failed: %s\n", strerror(err), 0, 0);
+       if (restart_listen(ciptr) == -1)
+       {
+               priv->listen_list= listen_list;
+               listen_list= ciptr;
+       }
+}
+
+static int
+restart_listen(ciptr)
+XtransConnInfo ciptr;
+{
+       char *tcp_device;
+       nwio_tcpconf_t tcpconf;
+       nwio_tcpcl_t tcpcl;
+       int fd, r, s_errno, flags;
+       struct private *priv;
+       nbio_ref_t ref;
+
+       PRMSG(2, ":restart_listen(%d)\n", ciptr->fd, 0, 0);
+
+       nbio_unregister(ciptr->fd);
+
+       if ((tcp_device= getenv("TCP_DEVICE")) == NULL)
+               tcp_device= TCP_DEVICE;
+
+       if ((fd= open(tcp_device, O_RDWR)) == -1)
+       {
+               PRMSG(1, ":restart_listen: open '%s' failed: %s\n",
+                       tcp_device, strerror(errno), 0);
+               return -1;
+       }
+       PRMSG(5, ":restart_listen: fd= '%d'\n", fd, 0, 0);
+       if (fd != ciptr->fd)
+       {
+               if (dup2(fd, ciptr->fd) == -1)
+                       abort();        /* no way to recover */
+               close(fd);
+       }
+       fd= ciptr->fd;
+       ref.ref_ptr= ciptr;
+       nbio_register(fd);
+       nbio_setcallback(fd, ASIO_IOCTL, listen_cb, ref);
+
+       priv= (struct private *)ciptr->priv;
+
+       tcpconf.nwtc_flags= NWTC_SHARED | NWTC_UNSET_RA | NWTC_UNSET_RP;
+       tcpconf.nwtc_locport= priv->listen_port;
+       tcpconf.nwtc_flags |= NWTC_LP_SET;
+
+       if (ioctl(ciptr->fd, NWIOSTCPCONF, &tcpconf) == -1)
+       {
+               PRMSG(1,
+               ":restart_listen: NWIOSTCPCONF failed: %s\n",
+                       strerror(errno),0, 0);
+               return -1;
+       }
+
+       flags= fcntl(ciptr->fd, F_GETFD);
+       if (flags == -1)
+       {
+               PRMSG(1,
+               ":restart_listen: fcntl F_GETFD failed: %s\n",
+                       strerror(errno), 0, 0);
+               return -1;
+       }
+       if (fcntl(ciptr->fd, F_SETFD, flags | FD_ASYNCHIO) == -1)
+       {
+               PRMSG(1,
+               ":restart_listen: fcntl F_SETFD failed: %s\n",
+                       strerror(errno), 0, 0);
+               return -1;
+       }
+
+       tcpcl.nwtcl_flags= 0;
+       r= ioctl(ciptr->fd, NWIOTCPLISTEN, &tcpcl);
+       s_errno= errno;
+
+       if (fcntl(ciptr->fd, F_SETFD, flags) == -1)
+       {
+               PRMSG(1,
+               ":restart_listen: fcntl F_SETFD failed: %s\n",
+                       strerror(errno), 0, 0);
+               return -1;
+       }
+
+       if (r == -1 && s_errno == EINPROGRESS)
+       {
+               nbio_inprogress(ciptr->fd, ASIO_IOCTL, 1 /* read */,
+                       1 /* write */, 0 /* exception */);
+               return 0;
+       }
+       if (r == 0)
+       {
+               priv->listen_completed= 1;
+               return 0;
+       }
+       errno= s_errno;
+       PRMSG(1, ":restart_listen: NWIOTCPLISTEN failed: %s\n",
+               strerror(errno), 0, 0);
+       return -1;
+}
+
+
+Xtransport     TRANS(MnxINETFuncs) =
+{
+       /* Minix TCP Interface */
+       "inet",
+       0,
+#ifdef TRANS_CLIENT
+       TRANS(MnxTcpOpenCOTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+       TRANS(MnxTcpOpenCOTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+       TRANS(MnxTcpOpenCLTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+       TRANS(MnxTcpOpenCLTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_REOPEN
+       TRANS(MnxTcpReopenCOTSServer),
+       TRANS(MnxTcpReopenCLTSServer),
+#endif
+       TRANS(MnxTcpSetOption),
+#ifdef TRANS_SERVER
+       TRANS(MnxTcpCreateListener),
+       TRANS(MnxTcpResetListener),
+       TRANS(MnxTcpAccept),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+       TRANS(MnxTcpConnect),
+#endif /* TRANS_CLIENT */
+       TRANS(MnxTcpBytesReadable),
+       TRANS(MnxTcpRead),
+       TRANS(MnxTcpWrite),
+       TRANS(MnxTcpReadv),
+       TRANS(MnxTcpWritev),
+       TRANS(MnxTcpDisconnect),
+       TRANS(MnxTcpClose),
+       TRANS(MnxTcpClose),
+};
+
+Xtransport     TRANS(MnxTCPFuncs) =
+{
+       /* Minix TCP Interface */
+       "tcp",
+       TRANS_ALIAS,
+#ifdef TRANS_CLIENT
+       TRANS(MnxTcpOpenCOTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+       TRANS(MnxTcpOpenCOTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+       TRANS(MnxTcpOpenCLTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+       TRANS(MnxTcpOpenCLTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_REOPEN
+       TRANS(MnxTcpReopenCOTSServer),
+       TRANS(MnxTcpReopenCLTSServer),
+#endif
+       TRANS(MnxTcpSetOption),
+#ifdef TRANS_SERVER
+       TRANS(MnxTcpCreateListener),
+       TRANS(MnxTcpResetListener),
+       TRANS(MnxTcpAccept),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+       TRANS(MnxTcpConnect),
+#endif /* TRANS_CLIENT */
+       TRANS(MnxTcpBytesReadable),
+       TRANS(MnxTcpRead),
+       TRANS(MnxTcpWrite),
+       TRANS(MnxTcpReadv),
+       TRANS(MnxTcpWritev),
+       TRANS(MnxTcpDisconnect),
+       TRANS(MnxTcpClose),
+       TRANS(MnxTcpClose),
+};