a9dfc21da6427416374ee3c348c0f5b5bb651730
[framework/uifw/xorg/lib/xtrans.git] / Xtranstli.c
1 /*
2
3 Copyright 1993, 1994, 1998  The Open Group
4
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
9 documentation.
10
11 The above copyright notice and this permission notice shall be included
12 in all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 OTHER DEALINGS IN THE SOFTWARE.
21
22 Except as contained in this notice, the name of The Open Group shall
23 not be used in advertising or otherwise to promote the sale, use or
24 other dealings in this Software without prior written authorization
25 from The Open Group.
26
27  * Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA
28  *
29  * All Rights Reserved
30  *
31  * Permission to use, copy, modify, and distribute this software and its
32  * documentation for any purpose and without fee is hereby granted, provided
33  * that the above copyright notice appear in all copies and that both that
34  * copyright notice and this permission notice appear in supporting
35  * documentation, and that the name NCR not be used in advertising
36  * or publicity pertaining to distribution of the software without specific,
37  * written prior permission.  NCR makes no representations about the
38  * suitability of this software for any purpose.  It is provided "as is"
39  * without express or implied warranty.
40  *
41  * NCR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
42  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
43  * NO EVENT SHALL NCR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
44  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
45  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
46  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
47  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
48  */
49
50 #include <sys/un.h>
51 #include <stropts.h>
52 #include <poll.h>
53 #include <tiuser.h>
54
55 #include <netdir.h>
56 #include <netconfig.h>
57
58
59 /*
60  * This is the TLI implementation of the X Transport service layer
61  */
62
63 typedef struct _TLItrans2dev {
64     char        *transname;
65     char        *protofamily;
66     char        *devcotsname;
67     char        *devcltsname;
68     int family;
69 } TLItrans2dev;
70
71 static TLItrans2dev TLItrans2devtab[] = {
72         {"inet","inet","/dev/tcp","/dev/udp",AF_INET},
73         {"tcp","inet","/dev/tcp","/dev/udp",AF_INET},
74         {"tli","loopback","/dev/ticots","/dev/ticlts",AF_UNIX},
75 };
76
77 #define NUMTLIFAMILIES (sizeof(TLItrans2devtab)/sizeof(TLItrans2dev))
78     
79 /*
80  * The local TLI connection, is a form of a local connection, so use a
81  * sockaddr_un for the address so that it will be treated just like the other
82  * local transports such as UNIX domain sockets, pts, and named.
83  */
84     
85 #if defined(X11_t)
86 #define TLINODENAME     "TLI:xserver"
87 #endif
88     
89 #if defined(XIM_t)
90 #define TLINODENAME     "TLI:xim"
91 #endif
92     
93 #if defined(FS_t) || defined(FONT_t)
94 #define TLINODENAME     "TLI:fontserver"
95 #endif
96     
97 #if defined(ICE_t)
98 #define TLINODENAME     "TLI:ICE"
99 #endif
100     
101 #if defined(TEST_t)
102 #define TLINODENAME     "TLI:test"
103 #endif
104     
105 #ifndef PORTBUFSIZE
106 #ifdef TRANS_SERVER
107 #define PORTBUFSIZE     64
108 #else
109 #ifdef TRANS_CLIENT
110 #define PORTBUFSIZE     64
111 #endif
112 #endif
113 #endif
114
115
116 /*
117  * These are some utility function used by the real interface function below.
118  */
119
120 static int
121 TRANS(TLISelectFamily)(char *family)
122
123 {
124     int     i;
125     
126     PRMSG(3,"TLISelectFamily(%s)\n", family, 0,0 );
127     
128     for(i=0;i<NUMTLIFAMILIES;i++)
129     {
130         if( !strcmp(family,TLItrans2devtab[i].transname) )
131             return i;
132     }
133     return -1;
134 }
135
136
137 /*
138  * This function gets the local address of the transport and stores it in the
139  * XtransConnInfo structure for the connection.
140  */
141
142 static int
143 TRANS(TLIGetAddr)(XtransConnInfo ciptr)
144
145 {
146     Xtransaddr          sockname;
147     struct netbuf       netbuf;
148     
149     PRMSG(3,"TLIGetAddr(%x)\n", ciptr, 0,0 );
150     
151     netbuf.buf=(char *)&sockname;
152     netbuf.len=sizeof(sockname);
153     netbuf.maxlen=sizeof(sockname);
154     
155     if( t_getname(ciptr->fd,&netbuf,LOCALNAME) < 0 )
156     {
157         PRMSG(1,"TLIGetAddr: t_getname(LOCALNAME) failed: %d\n",
158               errno, 0,0 );
159         return -1;
160     }
161     
162     PRMSG(4,"TLIGetAddr: got family %d len %d\n",
163           ((struct sockaddr *) &sockname)->sa_family ,netbuf.len, 0 );
164     
165     /*
166      * Everything looks good: fill in the XtransConnInfo structure.
167      */
168     
169     if( ciptr->addr )
170         xfree(ciptr->addr);
171     
172     if( (ciptr->addr=(char *)xalloc(netbuf.len)) == NULL )
173     {
174         PRMSG(1, "TLIGetAddr: Can't allocate space for the addr\n",
175               0,0,0);
176         return -1;
177     }
178     
179     ciptr->family=((struct sockaddr *) &sockname)->sa_family;
180     ciptr->addrlen=netbuf.len;
181     memcpy(ciptr->addr,&sockname,ciptr->addrlen);
182     
183     return 0;
184 }
185
186
187 /*
188  * This function gets the remote address of the socket and stores it in the
189  * XtransConnInfo structure for the connection.
190  */
191
192 static int
193 TRANS(TLIGetPeerAddr)(XtransConnInfo ciptr)
194
195 {
196     Xtransaddr          sockname;
197     struct netbuf       netbuf;
198     
199     PRMSG(3,"TLIGetPeerAddr(%x)\n", ciptr, 0,0 );
200     
201     netbuf.buf=(char *)&sockname;
202     netbuf.len=sizeof(sockname);
203     netbuf.maxlen=sizeof(sockname);
204     
205     if( t_getname(ciptr->fd,&netbuf,REMOTENAME) < 0 )
206     {
207         PRMSG(1,"TLIGetPeerAddr: t_getname(REMOTENAME) failed: %d\n",
208               errno, 0,0 );
209         return -1;
210     }
211     
212     PRMSG(4,"TLIGetPeerAddr: got family %d len %d\n",
213           ((struct sockaddr *) &sockname)->sa_family ,netbuf.len, 0 );
214     
215     /*
216      * Everything looks good: fill in the XtransConnInfo structure.
217      */
218     
219     if( ciptr->peeraddr )
220         xfree(ciptr->peeraddr);
221     
222     if( (ciptr->peeraddr=(char *)xalloc(netbuf.len)) == NULL )
223     {
224         PRMSG(1,
225               "TLIGetPeerAddr: Can't allocate space for the addr\n",
226               0,0,0);
227         return -1;
228     }
229     
230     ciptr->peeraddrlen=netbuf.len;
231     memcpy(ciptr->peeraddr,&sockname,ciptr->peeraddrlen);
232     
233     return 0;
234 }
235
236
237 /*
238  * This function will establish a local name for the transport. This function
239  * do extra work for the local tli connection. It must create a sockaddr_un
240  * format address so that it will look like an AF_UNIX connection to the
241  * higher layer.
242  *
243  * This function will only be called by the OPENC?TSClient() functions since
244  * the local address is set up in the CreateListner() for the server ends.
245  */
246
247 static int
248 TRANS(TLITLIBindLocal)(int fd, int family, char *port)
249
250 {
251     struct sockaddr_un  *sunaddr=NULL;
252     struct t_bind       *req=NULL;
253     
254     PRMSG(2, "TLITLIBindLocal(%d,%d,%s)\n", fd, family, port);
255     
256     if( family == AF_UNIX )
257     {
258         if( (req=(struct t_bind *)t_alloc(fd,T_BIND,0)) == NULL )
259         {
260             PRMSG(1,
261                   "TLITLIBindLocal() failed to allocate a t_bind\n",
262                   0,0,0 );
263             return -1;
264         }
265         
266         if( (sunaddr=(struct sockaddr_un *)
267              malloc(sizeof(struct sockaddr_un))) == NULL )
268         {
269             PRMSG(1,
270                   "TLITLIBindLocal: failed to allocate a sockaddr_un\n",
271                   0,0,0 );
272             t_free((char *)req,T_BIND);
273             return -1;
274         }
275         
276         sunaddr->sun_family=AF_UNIX;
277         
278 #ifdef nuke
279         if( *port == '/' ) { /* A full pathname */
280             (void) strcpy(sunaddr->sun_path, port);
281         } else {
282             (void) sprintf(sunaddr->sun_path,"%s%s", TLINODENAME, port );
283         }
284 #endif /*NUKE*/
285         
286         (void) sprintf(sunaddr->sun_path,"%s%d",
287                        TLINODENAME, getpid()^time(NULL) );
288         
289         PRMSG(4, "TLITLIBindLocal: binding to %s\n",
290               sunaddr->sun_path, 0,0);
291         
292         req->addr.buf=(char *)sunaddr;
293         req->addr.len=sizeof(*sunaddr);
294         req->addr.maxlen=sizeof(*sunaddr);
295     }
296     
297     if( t_bind(fd, req, NULL) < 0 )
298     {
299         PRMSG(1,
300               "TLIBindLocal: Unable to bind TLI device to %s\n",
301               port, 0,0 );
302         if (sunaddr)
303             free((char *) sunaddr);
304         if (req)
305             t_free((char *)req,T_BIND);
306         return -1;
307     }
308     return 0;
309 }
310
311 static XtransConnInfo
312 TRANS(TLIOpen)(char *device)
313
314 {
315     XtransConnInfo      ciptr;
316     
317     PRMSG(3,"TLIOpen(%s)\n", device, 0,0 );
318     
319     if( (ciptr=(XtransConnInfo)xcalloc(1,sizeof(struct _XtransConnInfo))) == NULL )
320     {
321         PRMSG(1, "TLIOpen: calloc failed\n", 0,0,0 );
322         return NULL;
323     }
324     
325     if( (ciptr->fd=t_open( device, O_RDWR, NULL )) < 0 )
326     {
327         PRMSG(1, "TLIOpen: t_open failed for %s\n", device, 0,0 );
328         free(ciptr);
329         return NULL;
330     }
331     
332     return ciptr;
333 }
334
335
336 #ifdef TRANS_REOPEN
337
338 static XtransConnInfo
339 TRANS(TLIReopen)(char *device, int fd, char *port)
340
341 {
342     XtransConnInfo      ciptr;
343     
344     PRMSG(3,"TLIReopen(%s,%d, %s)\n", device, fd, port );
345     
346     if (t_sync (fd) < 0)
347     {
348         PRMSG(1, "TLIReopen: t_sync failed\n", 0,0,0 );
349         return NULL;
350     }
351
352     if( (ciptr=(XtransConnInfo)xcalloc(1,sizeof(struct _XtransConnInfo))) == NULL )
353     {
354         PRMSG(1, "TLIReopen: calloc failed\n", 0,0,0 );
355         return NULL;
356     }
357     
358     ciptr->fd = fd;
359     
360     return ciptr;
361 }
362
363 #endif /* TRANS_REOPEN */
364
365
366 static  int
367 TRANS(TLIAddrToNetbuf)(int tlifamily, char *host, char *port, 
368                        struct netbuf *netbufp)
369
370 {
371     struct netconfig *netconfigp;
372     struct nd_hostserv  nd_hostserv;
373     struct nd_addrlist *nd_addrlistp = NULL;
374     void *handlep;
375     long lport;
376     
377     PRMSG(3,"TLIAddrToNetbuf(%d,%s,%s)\n", tlifamily, host, port );
378     
379     if( (handlep=setnetconfig()) == NULL )
380         return -1;
381
382     lport = strtol (port, (char**)NULL, 10);
383     if (lport < 1024 || lport > USHRT_MAX)
384         return -1;
385     
386     nd_hostserv.h_host = host;
387     if( port && *port ) {
388         nd_hostserv.h_serv = port;
389     } else {
390         nd_hostserv.h_serv = NULL;
391     }
392     
393     while( (netconfigp=getnetconfig(handlep)) != NULL )
394     {
395         if( strcmp(netconfigp->nc_protofmly,
396                    TLItrans2devtab[tlifamily].protofamily) != 0 )
397             continue;
398         PRMSG(5,"TLIAddrToNetbuf: Trying to resolve %s.%s for %s\n",
399               host, port, TLItrans2devtab[tlifamily].protofamily );
400         if( netdir_getbyname(netconfigp,&nd_hostserv, &nd_addrlistp) == 0 )
401         {
402             /* we have at least one address to use */
403             
404             PRMSG(5, "TLIAddrToNetbuf: found address for %s.%s\n", host, port, 0 );
405             PRMSG(5, "TLIAddrToNetbuf: %s\n",taddr2uaddr(netconfigp,nd_addrlistp->n_addrs),
406                   0,0 );
407             
408             memcpy(netbufp->buf,nd_addrlistp->n_addrs->buf,
409                    nd_addrlistp->n_addrs->len);
410             netbufp->len=nd_addrlistp->n_addrs->len;
411             endnetconfig(handlep);
412             return 0;
413         }
414     }
415     endnetconfig(handlep);
416     
417     return -1;
418 }
419
420 /*
421  * These functions are the interface supplied in the Xtransport structure
422  */
423
424 #ifdef TRANS_CLIENT
425
426 static XtransConnInfo
427 TRANS(TLIOpenCOTSClient)(Xtransport *thistrans, char *protocol, 
428                          char *host, char *port)
429
430 {
431     XtransConnInfo      ciptr;
432     int                 i;
433     
434     PRMSG(2,"TLIOpenCOTSClient(%s,%s,%s)\n", protocol, host, port );
435     
436     if( (i=TRANS(TLISelectFamily)(thistrans->TransName)) < 0 )
437     {
438         PRMSG(1,"TLIOpenCOTSClient: Unable to determine device for %s\n",
439               thistrans->TransName, 0,0 );
440         return NULL;
441     }
442     
443     if( (ciptr=TRANS(TLIOpen)(TLItrans2devtab[i].devcotsname)) == NULL )
444     {
445         PRMSG(1,"TLIOpenCOTSClient: Unable to open device for %s\n",
446               thistrans->TransName, 0,0 );
447         return NULL;
448     }
449     
450     if( TRANS(TLITLIBindLocal)(ciptr->fd,TLItrans2devtab[i].family,port) < 0 )
451     {
452         PRMSG(1,
453               "TLIOpenCOTSClient: ...TLITLIBindLocal() failed: %d\n",
454               errno, 0,0 );
455         t_close(ciptr->fd);
456         xfree(ciptr);
457         return NULL;
458     }
459     
460     if( TRANS(TLIGetAddr)(ciptr) < 0 )
461     {
462         PRMSG(1,
463               "TLIOpenCOTSClient: ...TLIGetAddr() failed: %d\n",
464               errno, 0,0 );
465         t_close(ciptr->fd);
466         xfree(ciptr);
467         return NULL;
468     }
469     
470     /* Save the TLIFamily for later use in TLIAddrToNetbuf() lookups */
471     ciptr->index = i;
472     
473     return ciptr;
474 }
475
476 #endif /* TRANS_CLIENT */
477
478
479 #ifdef TRANS_SERVER
480
481 static XtransConnInfo
482 TRANS(TLIOpenCOTSServer)(Xtransport *thistrans, char *protocol, 
483                          char *host, char *port)
484
485 {
486     XtransConnInfo      ciptr;
487     int                 i;
488     
489     PRMSG(2,"TLIOpenCOTSServer(%s,%s,%s)\n", protocol, host, port );
490     
491     if( (i=TRANS(TLISelectFamily)(thistrans->TransName)) < 0 )
492     {
493         PRMSG(1,
494               "TLIOpenCOTSServer: Unable to determine device for %s\n",
495               thistrans->TransName, 0,0 );
496         return NULL;
497     }
498     
499     if( (ciptr=TRANS(TLIOpen)(TLItrans2devtab[i].devcotsname)) == NULL )
500     {
501         PRMSG(1,
502               "TLIOpenCOTSServer: Unable to open device for %s\n",
503               thistrans->TransName, 0,0 );
504         return NULL;
505     }
506     
507     /* Set the family type */
508
509     ciptr->family = TLItrans2devtab[i].family;
510
511
512     /* Save the TLIFamily for later use in TLIAddrToNetbuf() lookups */
513     
514     ciptr->index = i;
515     
516     return ciptr;
517 }
518
519 #endif /* TRANS_SERVER */
520
521
522 #ifdef TRANS_CLIENT
523
524 static XtransConnInfo
525 TRANS(TLIOpenCLTSClient)(Xtransport *thistrans, char *protocol, 
526                          char *host, char *port)
527
528 {
529     XtransConnInfo      ciptr;
530     int                 i;
531     
532     PRMSG(2,"TLIOpenCLTSClient(%s,%s,%s)\n", protocol, host, port );
533     
534     if( (i=TRANS(TLISelectFamily)(thistrans->TransName)) < 0 )
535     {
536         PRMSG(1,
537               "TLIOpenCLTSClient: Unable to determine device for %s\n",
538               thistrans->TransName, 0,0 );
539         return NULL;
540     }
541     
542     if( (ciptr=TRANS(TLIOpen)(TLItrans2devtab[i].devcltsname)) == NULL )
543     {
544         PRMSG(1,
545               "TLIOpenCLTSClient: Unable to open device for %s\n",
546               thistrans->TransName, 0,0 );
547         return NULL;
548     }
549     
550     if( TRANS(TLITLIBindLocal)(ciptr->fd,TLItrans2devtab[i].family,port) < 0 )
551     {
552         PRMSG(1,
553               "TLIOpenCLTSClient: ...TLITLIBindLocal() failed: %d\n",
554               errno, 0,0 );
555         t_close(ciptr->fd);
556         xfree(ciptr);
557         return NULL;
558     }
559     
560     if( TRANS(TLIGetAddr)(ciptr) < 0 )
561     {
562         PRMSG(1,
563               "TLIOpenCLTSClient: ...TLIGetPeerAddr() failed: %d\n",
564               errno, 0,0 );
565         t_close(ciptr->fd);
566         xfree(ciptr);
567         return NULL;
568     }
569     
570     return ciptr;
571 }                       
572
573 #endif /* TRANS_CLIENT */
574
575
576 #ifdef TRANS_SERVER
577
578 static XtransConnInfo
579 TRANS(TLIOpenCLTSServer)(Xtransport *thistrans, char *protocol, 
580                          char *host, char *port)
581
582 {
583     XtransConnInfo      ciptr;
584     int                 i;
585     
586     PRMSG(2,"TLIOpenCLTSServer(%s,%s,%s)\n", protocol, host, port );
587     
588     if( (i=TRANS(TLISelectFamily)(thistrans->TransName)) < 0 )
589     {
590         PRMSG(1,
591               "TLIOpenCLTSServer: Unable to determine device for %s\n",
592               thistrans->TransName, 0,0 );
593         return NULL;
594     }
595     
596     if( (ciptr=TRANS(TLIOpen)(TLItrans2devtab[i].devcltsname)) == NULL )
597     {
598         PRMSG(1,
599               "TLIOpenCLTSServer: Unable to open device for %s\n",
600               thistrans->TransName, 0,0 );
601         return NULL;
602     }
603     
604     return ciptr;
605 }                       
606
607 #endif /* TRANS_SERVER */
608
609
610 #ifdef TRANS_REOPEN
611
612 static XtransConnInfo
613 TRANS(TLIReopenCOTSServer)(Xtransport *thistrans, int fd, char *port)
614
615 {
616     XtransConnInfo      ciptr;
617     int                 i;
618     
619     PRMSG(2,"TLIReopenCOTSServer(%d, %s)\n", fd, port, 0 );
620     
621     if( (i=TRANS(TLISelectFamily)(thistrans->TransName)) < 0 )
622     {
623         PRMSG(1,
624               "TLIReopenCOTSServer: Unable to determine device for %s\n",
625               thistrans->TransName, 0,0 );
626         return NULL;
627     }
628
629     if( (ciptr=TRANS(TLIReopen)(
630         TLItrans2devtab[i].devcotsname, fd, port)) == NULL )
631     {
632         PRMSG(1,
633               "TLIReopenCOTSServer: Unable to open device for %s\n",
634               thistrans->TransName, 0,0 );
635         return NULL;
636     }
637     
638     /* Save the TLIFamily for later use in TLIAddrToNetbuf() lookups */
639     
640     ciptr->index = i;
641     
642     return ciptr;
643 }
644
645
646 static XtransConnInfo
647 TRANS(TLIReopenCLTSServer)(Xtransport *thistrans, int fd, char *port)
648
649 {
650     XtransConnInfo      ciptr;
651     int                 i;
652     
653     PRMSG(2,"TLIReopenCLTSServer(%d, %s)\n", fd, port, 0 );
654     
655     if( (i=TRANS(TLISelectFamily)(thistrans->TransName)) < 0 )
656     {
657         PRMSG(1,
658               "TLIReopenCLTSServer: Unable to determine device for %s\n",
659               thistrans->TransName, 0,0 );
660         return NULL;
661     }
662
663     if( (ciptr=TRANS(TLIReopen)(
664         TLItrans2devtab[i].devcltsname, fd, port)) == NULL )
665     {
666         PRMSG(1,
667               "TLIReopenCLTSServer: Unable to open device for %s\n",
668               thistrans->TransName, 0,0 );
669         return NULL;
670     }
671     
672     ciptr->index = i;
673
674     return ciptr;
675 }                       
676
677 #endif /* TRANS_REOPEN */
678
679
680 static int
681 TRANS(TLISetOption)(XtransConnInfo ciptr, int option, int arg)
682
683 {
684     PRMSG(2,"TLISetOption(%d,%d,%d)\n", ciptr->fd, option, arg );
685     
686     return -1;
687 }
688
689
690 #ifdef TRANS_SERVER
691
692 static int
693 TRANS(TLICreateListener)(XtransConnInfo ciptr, struct t_bind *req)
694
695 {
696     struct t_bind       *ret;
697     
698     PRMSG(2,"TLICreateListener(%x->%d,%x)\n", ciptr, ciptr->fd, req );
699     
700     if( (ret=(struct t_bind *)t_alloc(ciptr->fd,T_BIND,T_ALL)) == NULL )
701     {
702         PRMSG(1, "TLICreateListener: failed to allocate a t_bind\n",
703               0,0,0 );
704         t_free((char *)req,T_BIND);
705         return TRANS_CREATE_LISTENER_FAILED;
706     }
707     
708     if( t_bind(ciptr->fd, req, ret) < 0 )
709     {
710         PRMSG(1, "TLICreateListener: t_bind failed\n", 0,0,0 );
711         t_free((char *)req,T_BIND);
712         t_free((char *)ret,T_BIND);
713         return TRANS_CREATE_LISTENER_FAILED;
714     }
715     
716     if( memcmp(req->addr.buf,ret->addr.buf,req->addr.len) != 0 )
717     {
718         PRMSG(1, "TLICreateListener: unable to bind to %x\n",
719               req, 0,0 );
720         t_free((char *)req,T_BIND);
721         t_free((char *)ret,T_BIND);
722         return TRANS_ADDR_IN_USE;
723     }
724     
725     /*
726      * Everything looks good: fill in the XtransConnInfo structure.
727      */
728     
729     if( (ciptr->addr=(char *)xalloc(ret->addr.len)) == NULL )
730     {
731         PRMSG(1,
732               "TLICreateListener: Unable to allocate space for the address\n",
733               0,0,0 );
734         t_free((char *)req,T_BIND);
735         t_free((char *)ret, T_BIND);
736         return TRANS_CREATE_LISTENER_FAILED;
737     }
738     
739     ciptr->addrlen=ret->addr.len;
740     memcpy(ciptr->addr,ret->addr.buf,ret->addr.len);
741     
742     t_free((char *)req,T_BIND);
743     t_free((char *)ret, T_BIND);
744     
745     return 0;
746 }
747
748
749 static int
750 TRANS(TLIINETCreateListener)(XtransConnInfo ciptr, char *port, unsigned int flags)
751
752 {
753     char    portbuf[PORTBUFSIZE];
754     struct t_bind       *req;
755     struct sockaddr_in  *sinaddr;
756     long                tmpport;
757     
758     PRMSG(2,"TLIINETCreateListener(%x->%d,%s)\n", ciptr,
759         ciptr->fd, port ? port : "NULL" );
760     
761 #ifdef X11_t
762     /*
763      * X has a well known port, that is transport dependent. It is easier
764      * to handle it here, than try and come up with a transport independent
765      * representation that can be passed in and resolved the usual way.
766      *
767      * The port that is passed here is really a string containing the idisplay
768      * from ConnectDisplay().
769      */
770     
771     if (is_numeric (port))
772     {
773         tmpport = X_TCP_PORT + strtol (port, (char**)NULL, 10);
774         sprintf(portbuf,"%u", tmpport);
775         port = portbuf;
776     }
777 #endif
778     
779     if( (req=(struct t_bind *)t_alloc(ciptr->fd,T_BIND,T_ALL)) == NULL )
780     {
781         PRMSG(1,
782             "TLIINETCreateListener: failed to allocate a t_bind\n",
783             0,0,0 );
784         return TRANS_CREATE_LISTENER_FAILED;
785     }
786
787     if( port && *port ) {
788         if(TRANS(TLIAddrToNetbuf)(ciptr->index,HOST_SELF,port,&(req->addr)) < 0)
789         {
790             PRMSG(1,
791                   "TLIINETCreateListener: can't resolve name:HOST_SELF.%s\n",
792                   port, 0,0 );
793             t_free((char *)req,T_BIND);
794             return TRANS_CREATE_LISTENER_FAILED;
795         }
796     } else {
797         sinaddr=(struct sockaddr_in *) req->addr.buf;
798         sinaddr->sin_family=AF_INET;
799         sinaddr->sin_port=htons(0);
800         sinaddr->sin_addr.s_addr=0;
801     }
802
803     /* Set the qlen */
804
805     req->qlen=1;
806     
807     return TRANS(TLICreateListener)(ciptr, req);
808 }
809
810
811 static int
812 TRANS(TLITLICreateListener)(XtransConnInfo ciptr, char *port, unsigned int flags)
813
814 {
815     struct t_bind       *req;
816     struct sockaddr_un  *sunaddr;
817     int                 ret_value;
818     
819     PRMSG(2,"TLITLICreateListener(%x->%d,%s)\n", ciptr, ciptr->fd,
820         port ? port : "NULL");
821     
822     if( (req=(struct t_bind *)t_alloc(ciptr->fd,T_BIND,0)) == NULL )
823     {
824         PRMSG(1,
825               "TLITLICreateListener: failed to allocate a t_bind\n",
826               0,0,0 );
827         return TRANS_CREATE_LISTENER_FAILED;
828     }
829     
830     if( (sunaddr=(struct sockaddr_un *)
831          malloc(sizeof(struct sockaddr_un))) == NULL )
832     {
833         PRMSG(1,
834               "TLITLICreateListener: failed to allocate a sockaddr_un\n",
835               0,0,0 );
836         t_free((char *)req,T_BIND);
837         return TRANS_CREATE_LISTENER_FAILED;
838     }
839     
840     sunaddr->sun_family=AF_UNIX;
841     if( port && *port ) {
842         if( *port == '/' ) { /* A full pathname */
843             (void) strcpy(sunaddr->sun_path, port);
844         } else {
845             (void) sprintf(sunaddr->sun_path,"%s%s", TLINODENAME, port );
846         }
847     } else {
848         (void) sprintf(sunaddr->sun_path,"%s%d", TLINODENAME, getpid());
849     }
850     
851     req->addr.buf=(char *)sunaddr;
852     req->addr.len=sizeof(*sunaddr);
853     req->addr.maxlen=sizeof(*sunaddr);
854     
855     /* Set the qlen */
856     
857     req->qlen=1;
858     
859     ret_value = TRANS(TLICreateListener)(ciptr, req);
860
861     free((char *) sunaddr);
862
863     return ret_value;
864 }
865
866
867 static XtransConnInfo
868 TRANS(TLIAccept)(XtransConnInfo ciptr, int *status)
869
870 {
871     struct t_call       *call;
872     XtransConnInfo      newciptr;
873     int i;
874     
875     PRMSG(2,"TLIAccept(%x->%d)\n", ciptr, ciptr->fd, 0 );
876     
877     if( (call=(struct t_call *)t_alloc(ciptr->fd,T_CALL,T_ALL)) == NULL )
878     {
879         PRMSG(1, "TLIAccept() failed to allocate a t_call\n", 0,0,0 );
880         *status = TRANS_ACCEPT_BAD_MALLOC;
881         return NULL;
882     }
883     
884     if( t_listen(ciptr->fd,call) < 0 )
885     {
886         extern char *t_errlist[];
887         extern int t_errno;
888         PRMSG(1, "TLIAccept() t_listen() failed\n", 0,0,0 );
889         PRMSG(1, "TLIAccept: %s\n", t_errlist[t_errno], 0,0 );
890         t_free((char *)call,T_CALL);
891         *status = TRANS_ACCEPT_MISC_ERROR;
892         return NULL;
893     }
894     
895     /*
896      * Now we need to set up the new endpoint for the incoming connection.
897      */
898     
899     i=ciptr->index; /* Makes the next line more readable */
900     
901     if( (newciptr=TRANS(TLIOpen)(TLItrans2devtab[i].devcotsname)) == NULL )
902     {
903         PRMSG(1, "TLIAccept() failed to open a new endpoint\n", 0,0,0 );
904         t_free((char *)call,T_CALL);
905         *status = TRANS_ACCEPT_MISC_ERROR;
906         return NULL;
907     }
908     
909     if( TRANS(TLITLIBindLocal)(newciptr->fd,TLItrans2devtab[i].family,"") < 0 )
910     {
911         PRMSG(1,
912               "TLIAccept: TRANS(TLITLIBindLocal)() failed: %d\n",
913               errno, 0,0 );
914         t_free((char *)call,T_CALL);
915         t_close(newciptr->fd);
916         xfree(newciptr);
917         *status = TRANS_ACCEPT_MISC_ERROR;
918         return NULL;
919     }
920     
921     
922     if( t_accept(ciptr->fd,newciptr->fd,call) < 0 )
923     {
924         extern char *t_errlist[];
925         extern int t_errno;
926         PRMSG(1, "TLIAccept() t_accept() failed\n", 0,0,0 );
927         PRMSG(1, "TLIAccept: %s\n", t_errlist[t_errno], 0,0 );
928         if( t_errno == TLOOK )
929         {
930             int evtype = t_look(ciptr->fd);
931             PRMSG(1, "TLIAccept() t_look() returned %d\n", evtype,0,0 );
932             switch( evtype )
933             {
934                 case T_DISCONNECT:
935                     if( t_rcvdis(ciptr->fd, NULL) < 0 )
936                     {
937                         PRMSG(1, "TLIAccept() t_rcvdis() failed\n", 0,0,0 );
938                         PRMSG(1, "TLIAccept: %s\n", t_errlist[t_errno], 0,0 );
939                     }
940                     break;
941                 default:
942                     break;
943             }
944         }
945         t_free((char *)call,T_CALL);
946         t_close(newciptr->fd);
947         free(newciptr);
948         *status = TRANS_ACCEPT_FAILED;
949         return NULL;
950     }
951     
952     t_free((char *)call,T_CALL);
953     
954     if( TRANS(TLIGetAddr)(newciptr) < 0 )
955     {
956         PRMSG(1,
957               "TLIAccept: TRANS(TLIGetPeerAddr)() failed: %d\n",
958               errno, 0,0 );
959         t_close(newciptr->fd);
960         xfree(newciptr);
961         *status = TRANS_ACCEPT_MISC_ERROR;
962         return NULL;
963     }
964     
965     if( TRANS(TLIGetPeerAddr)(newciptr) < 0 )
966     {
967         PRMSG(1,
968               "TLIAccept: TRANS(TLIGetPeerAddr)() failed: %d\n",
969               errno, 0,0 );
970         t_close(newciptr->fd);
971         xfree(newciptr->addr);
972         xfree(newciptr);
973         *status = TRANS_ACCEPT_MISC_ERROR;
974         return NULL;
975     }
976     
977     if( ioctl(newciptr->fd, I_POP,"timod") < 0 )
978     {
979         PRMSG(1, "TLIAccept() ioctl(I_POP, \"timod\") failed %d\n",
980               errno,0,0 );
981         t_close(newciptr->fd);
982         xfree(newciptr->addr);
983         xfree(newciptr);
984         *status = TRANS_ACCEPT_MISC_ERROR;
985         return NULL;
986     }
987     
988     if( ioctl(newciptr->fd, I_PUSH,"tirdwr") < 0 )
989     {
990         PRMSG(1, "TLIAccept() ioctl(I_PUSH,\"tirdwr\") failed %d\n",
991               errno,0,0 );
992         t_close(newciptr->fd);
993         xfree(newciptr->addr);
994         xfree(newciptr);
995         *status = TRANS_ACCEPT_MISC_ERROR;
996         return NULL;
997     }
998     
999     *status = 0;
1000
1001     return newciptr;
1002 }
1003
1004 #endif /* TRANS_SERVER */
1005
1006
1007 #ifdef TRANS_CLIENT
1008
1009 static int
1010 TRANS(TLIConnect)(XtransConnInfo ciptr, struct t_call *sndcall )
1011
1012 {
1013     PRMSG(2, "TLIConnect(%x->%d,%x)\n", ciptr, ciptr->fd, sndcall);
1014     
1015     if( t_connect(ciptr->fd,sndcall,NULL) < 0 )
1016     {
1017         extern char *t_errlist[];
1018         extern int t_errno;
1019         PRMSG(1, "TLIConnect() t_connect() failed\n", 0,0,0 );
1020         PRMSG(1, "TLIConnect: %s\n", t_errlist[t_errno], 0,0 );
1021         t_free((char *)sndcall,T_CALL);
1022         if (t_errno == TLOOK && t_look(ciptr->fd) == T_DISCONNECT)
1023         {
1024             t_rcvdis(ciptr->fd,NULL);
1025             return TRANS_TRY_CONNECT_AGAIN;
1026         }
1027         else
1028             return TRANS_CONNECT_FAILED;
1029     }
1030     
1031     t_free((char *)sndcall,T_CALL);
1032     
1033     /*
1034      * Sync up the address fields of ciptr.
1035      */
1036     
1037     if( TRANS(TLIGetAddr)(ciptr) < 0 )
1038     {
1039         PRMSG(1,
1040               "TLIConnect: ...TLIGetAddr() failed: %d\n",
1041               errno, 0,0 );
1042         return TRANS_CONNECT_FAILED;
1043     }
1044     
1045     if( TRANS(TLIGetPeerAddr)(ciptr) < 0 )
1046     {
1047         PRMSG(1,
1048               "TLIConnect: ...TLIGetPeerAddr() failed: %d\n",
1049               errno, 0,0 );
1050         return TRANS_CONNECT_FAILED;
1051     }
1052     
1053     if( ioctl(ciptr->fd, I_POP,"timod") < 0 )
1054     {
1055         PRMSG(1, "TLIConnect() ioctl(I_POP,\"timod\") failed %d\n",
1056               errno,0,0 );
1057         return TRANS_CONNECT_FAILED;
1058     }
1059     
1060     if( ioctl(ciptr->fd, I_PUSH,"tirdwr") < 0 )
1061     {
1062         PRMSG(1, "TLIConnect() ioctl(I_PUSH,\"tirdwr\") failed %d\n",
1063               errno,0,0 );
1064         return TRANS_CONNECT_FAILED;
1065     }
1066     
1067     return 0;
1068 }
1069
1070
1071 static int
1072 TRANS(TLIINETConnect)(XtransConnInfo ciptr, char *host, char *port)
1073
1074 {
1075     char        portbuf[PORTBUFSIZE];   
1076     struct      t_call  *sndcall;
1077     long        tmpport;
1078     
1079     PRMSG(2, "TLIINETConnect(%s,%s)\n", host, port, 0);
1080     
1081 #ifdef X11_t
1082     /*
1083      * X has a well known port, that is transport dependant. It is easier
1084      * to handle it here, than try and come up with a transport independent
1085      * representation that can be passed in and resolved the usual way.
1086      *
1087      * The port that is passed here is really a string containing the idisplay
1088      * from ConnectDisplay().
1089      */
1090     
1091     if (is_numeric (port))
1092     {
1093         tmpport = X_TCP_PORT + strtol (port, (char**)NULL, 10);
1094         sprintf(portbuf,"%u", tmpport );
1095         port = portbuf;
1096     }
1097 #endif
1098     
1099     if( (sndcall=(struct t_call *)t_alloc(ciptr->fd,T_CALL,T_ALL)) == NULL )
1100     {
1101         PRMSG(1, "TLIINETConnect() failed to allocate a t_call\n", 0,0,0 );
1102         return TRANS_CONNECT_FAILED;
1103     }
1104     
1105     if( TRANS(TLIAddrToNetbuf)(ciptr->index, host, port, &(sndcall->addr) ) < 0 )
1106     {
1107         PRMSG(1, "TLIINETConnect() unable to resolve name:%s.%s\n",
1108               host, port, 0 );
1109         t_free((char *)sndcall,T_CALL);
1110         return TRANS_CONNECT_FAILED;
1111     }
1112     
1113     return TRANS(TLIConnect)(ciptr, sndcall );
1114 }
1115
1116
1117 static int
1118 TRANS(TLITLIConnect)(XtransConnInfo ciptr, char *host, char *port)
1119
1120 {
1121     struct t_call       *sndcall;
1122     struct sockaddr_un  *sunaddr;
1123     int                 ret_value;
1124     
1125     PRMSG(2, "TLITLIConnect(%s,%s)\n", host, port, 0);
1126     
1127     if( (sndcall=(struct t_call *)t_alloc(ciptr->fd,T_CALL,T_OPT|T_UDATA)) == NULL )
1128     {
1129         PRMSG(1, "TLITLIConnect() failed to allocate a t_call\n", 0,0,0 );
1130         return TRANS_CONNECT_FAILED;
1131     }
1132     
1133     if( (sunaddr=(struct sockaddr_un *)
1134          malloc(sizeof(struct sockaddr_un))) == NULL )
1135     {
1136         PRMSG(1,
1137               "TLITLIConnect: failed to allocate a sockaddr_un\n",
1138               0,0,0 );
1139         t_free((char *)sndcall,T_CALL);
1140         return TRANS_CONNECT_FAILED;
1141     }
1142     
1143     sunaddr->sun_family=AF_UNIX;
1144     if( *port == '/' ||
1145         strncmp (port, TLINODENAME, strlen (TLINODENAME)) == 0) {
1146         /* Use the port as is */
1147         (void) strcpy(sunaddr->sun_path, port);
1148     } else {
1149         (void) sprintf(sunaddr->sun_path,"%s%s", TLINODENAME, port );
1150     }
1151
1152     sndcall->addr.buf=(char *)sunaddr;
1153     sndcall->addr.len=sizeof(*sunaddr);
1154     sndcall->addr.maxlen=sizeof(*sunaddr);
1155     
1156     ret_value = TRANS(TLIConnect)(ciptr, sndcall );
1157
1158     free((char *) sunaddr);
1159
1160     return ret_value;
1161 }
1162
1163 #endif /* TRANS_CLIENT */
1164
1165
1166 static int
1167 TRANS(TLIBytesReadable)(XtransConnInfo ciptr, BytesReadable_t *pend)
1168
1169 {
1170     int ret;
1171     struct pollfd filedes;
1172
1173     PRMSG(2, "TLIByteReadable(%x->%d,%x)\n", ciptr, ciptr->fd, pend );
1174
1175     /*
1176      * This function should detect hangup conditions. Use poll to check
1177      * if no data is present. On SVR4, the M_HANGUP message sits on the
1178      * streams head, and ioctl(N_READ) keeps returning 0 because there is
1179      * no data available. The hangup goes undetected, and the client hangs.
1180      */
1181     
1182     ret=ioctl(ciptr->fd, I_NREAD, (char *)pend);
1183
1184     if( ret != 0 )
1185         return ret; /* Data present or error */
1186
1187
1188     /* Zero data, or POLLHUP message */
1189
1190     filedes.fd=ciptr->fd;
1191     filedes.events=POLLIN;
1192
1193     ret=poll(&filedes, 1, 0);
1194  
1195     if( ret == 0 ) {
1196         *pend=0;
1197         return 0; /* Really, no data */
1198         }
1199
1200     if( ret < 0 )
1201         return -1; /* just pass back the error */
1202
1203     if( filedes.revents & (POLLHUP|POLLERR) ) /* check for hangup */
1204         return -1;
1205
1206     /* Should only get here if data arrived after the first ioctl() */
1207     return ioctl(ciptr->fd, I_NREAD, (char *)pend);
1208 }
1209
1210
1211 static int
1212 TRANS(TLIRead)(XtransConnInfo ciptr, char *buf, int size)
1213
1214 {
1215     PRMSG(2, "TLIRead(%d,%x,%d)\n", ciptr->fd, buf, size );
1216     
1217     return read(ciptr->fd,buf,size);
1218 }
1219
1220
1221 static int
1222 TRANS(TLIWrite)(XtransConnInfo ciptr, char *buf, int size)
1223
1224 {
1225     PRMSG(2, "TLIWrite(%d,%x,%d)\n", ciptr->fd, buf, size );
1226     
1227     return write(ciptr->fd,buf,size);
1228 }
1229
1230
1231 static int
1232 TRANS(TLIReadv)(XtransConnInfo ciptr, struct iovec *buf, int size)
1233
1234 {
1235     PRMSG(2, "TLIReadv(%d,%x,%d)\n", ciptr->fd, buf, size );
1236     
1237     return READV(ciptr,buf,size);
1238 }
1239
1240
1241 static int
1242 TRANS(TLIWritev)(XtransConnInfo ciptr, struct iovec *buf, int size)
1243
1244 {
1245     PRMSG(2, "TLIWritev(%d,%x,%d)\n", ciptr->fd, buf, size );
1246     
1247     return WRITEV(ciptr,buf,size);
1248 }
1249
1250
1251 static int
1252 TRANS(TLIDisconnect)(XtransConnInfo ciptr)
1253
1254 {
1255     PRMSG(2, "TLIDisconnect(%x->%d)\n", ciptr, ciptr->fd, 0 );
1256     
1257     /*
1258      * Restore the TLI modules so that the connection can be properly shutdown.
1259      * This avoids the situation where a connection goes into the TIME_WAIT
1260      * state, and the address remains unavailable for a while.
1261      */
1262     ioctl(ciptr->fd, I_POP,"tirdwr");
1263     ioctl(ciptr->fd, I_PUSH,"timod");
1264
1265     t_snddis(ciptr->fd,NULL);
1266     
1267     return 0;
1268 }
1269
1270
1271 static int
1272 TRANS(TLIClose)(XtransConnInfo ciptr)
1273
1274 {
1275     PRMSG(2, "TLIClose(%x->%d)\n", ciptr, ciptr->fd, 0 );
1276     
1277     t_unbind(ciptr->fd);
1278
1279     return (t_close(ciptr->fd));
1280 }
1281
1282
1283 static int
1284 TRANS(TLICloseForCloning)(XtransConnInfo ciptr)
1285
1286 {
1287     /*
1288      * Don't unbind.
1289      */
1290
1291     PRMSG(2, "TLICloseForCloning(%x->%d)\n", ciptr, ciptr->fd, 0 );
1292     
1293     return (t_close(ciptr->fd));
1294 }
1295
1296
1297 Xtransport      TRANS(TLITCPFuncs) = {
1298         /* TLI Interface */
1299         "tcp",
1300         0,
1301 #ifdef TRANS_CLIENT
1302         TRANS(TLIOpenCOTSClient),
1303 #endif /* TRANS_CLIENT */
1304 #ifdef TRANS_SERVER
1305         NULL,
1306         TRANS(TLIOpenCOTSServer),
1307 #endif /* TRANS_SERVER */
1308 #ifdef TRANS_CLIENT
1309         TRANS(TLIOpenCLTSClient),
1310 #endif /* TRANS_CLIENT */
1311 #ifdef TRANS_SERVER
1312         TRANS(TLIOpenCLTSServer),
1313 #endif /* TRANS_SERVER */
1314 #ifdef TRANS_REOPEN
1315         TRANS(TLIReopenCOTSServer),
1316         TRANS(TLIReopenCLTSServer),
1317 #endif
1318         TRANS(TLISetOption),
1319 #ifdef TRANS_SERVER
1320         TRANS(TLIINETCreateListener),
1321         NULL,                                   /* ResetListener */
1322         TRANS(TLIAccept),
1323 #endif /* TRANS_SERVER */
1324 #ifdef TRANS_CLIENT
1325         TRANS(TLIINETConnect),
1326 #endif /* TRANS_CLIENT */
1327         TRANS(TLIBytesReadable),
1328         TRANS(TLIRead),
1329         TRANS(TLIWrite),
1330         TRANS(TLIReadv),
1331         TRANS(TLIWritev),
1332         TRANS(TLIDisconnect),
1333         TRANS(TLIClose),
1334         TRANS(TLICloseForCloning),
1335 };
1336
1337 #ifdef TRANS_SERVER
1338 static char * inet_aliases[] = { "tcp", NULL };
1339 #endif
1340 Xtransport      TRANS(TLIINETFuncs) = {
1341         /* TLI Interface */
1342         "inet",
1343         TRANS_ALIAS,
1344 #ifdef TRANS_CLIENT
1345         TRANS(TLIOpenCOTSClient),
1346 #endif /* TRANS_CLIENT */
1347 #ifdef TRANS_SERVER
1348         inet_aliases,
1349         TRANS(TLIOpenCOTSServer),
1350 #endif /* TRANS_SERVER */
1351 #ifdef TRANS_CLIENT
1352         TRANS(TLIOpenCLTSClient),
1353 #endif /* TRANS_CLIENT */
1354 #ifdef TRANS_SERVER
1355         TRANS(TLIOpenCLTSServer),
1356 #endif /* TRANS_SERVER */
1357 #ifdef TRANS_REOPEN
1358         TRANS(TLIReopenCOTSServer),
1359         TRANS(TLIReopenCLTSServer),
1360 #endif
1361         TRANS(TLISetOption),
1362 #ifdef TRANS_SERVER
1363         TRANS(TLIINETCreateListener),
1364         NULL,                                   /* ResetListener */
1365         TRANS(TLIAccept),
1366 #endif /* TRANS_SERVER */
1367 #ifdef TRANS_CLIENT
1368         TRANS(TLIINETConnect),
1369 #endif /* TRANS_CLIENT */
1370         TRANS(TLIBytesReadable),
1371         TRANS(TLIRead),
1372         TRANS(TLIWrite),
1373         TRANS(TLIReadv),
1374         TRANS(TLIWritev),
1375         TRANS(TLIDisconnect),
1376         TRANS(TLIClose),
1377         TRANS(TLICloseForCloning),
1378 };
1379
1380 Xtransport      TRANS(TLITLIFuncs) = {
1381         /* TLI Interface */
1382         "tli",
1383         0,
1384 #ifdef TRANS_CLIENT
1385         TRANS(TLIOpenCOTSClient),
1386 #endif /* TRANS_CLIENT */
1387 #ifdef TRANS_SERVER
1388         NULL,
1389         TRANS(TLIOpenCOTSServer),
1390 #endif /* TRANS_SERVER */
1391 #ifdef TRANS_CLIENT
1392         TRANS(TLIOpenCLTSClient),
1393 #endif /* TRANS_CLIENT */
1394 #ifdef TRANS_SERVER
1395         TRANS(TLIOpenCLTSServer),
1396 #endif /* TRANS_SERVER */
1397 #ifdef TRANS_REOPEN
1398         TRANS(TLIReopenCOTSServer),
1399         TRANS(TLIReopenCLTSServer),
1400 #endif
1401         TRANS(TLISetOption),
1402 #ifdef TRANS_SERVER
1403         TRANS(TLITLICreateListener),
1404         NULL,                                   /* ResetListener */
1405         TRANS(TLIAccept),
1406 #endif /* TRANS_SERVER */
1407 #ifdef TRANS_CLIENT
1408         TRANS(TLITLIConnect),
1409 #endif /* TRANS_CLIENT */
1410         TRANS(TLIBytesReadable),
1411         TRANS(TLIRead),
1412         TRANS(TLIWrite),
1413         TRANS(TLIReadv),
1414         TRANS(TLIWritev),
1415         TRANS(TLIDisconnect),
1416         TRANS(TLIClose),
1417         TRANS(TLICloseForCloning),
1418 };