3 Copyright 1990, 1998 The Open Group
4 Copyright 2002-2004 Oswald Buddenhagen <ossi@kde.org>
6 Permission to use, copy, modify, distribute, and sell this software and its
7 documentation for any purpose is hereby granted without fee, provided that
8 the above copyright notice appear in all copies and that both that
9 copyright notice and this permission notice appear in supporting
12 The above copyright notice and this permission notice shall be included
13 in all copies or substantial portions of the Software.
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
19 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21 OTHER DEALINGS IN THE SOFTWARE.
23 Except as contained in this notice, the name of a copyright holder shall
24 not be used in advertising or otherwise to promote the sale, use or
25 other dealings in this Software without prior written authorization
26 from the copyright holder.
31 * xdm - display manager daemon
32 * Author: Keith Packard, MIT X Consortium
39 #include "dm_socket.h"
44 # include <sys/sockio.h>
46 #include <arpa/inet.h>
48 #include <sys/ioctl.h>
50 # ifdef WINTCP /* NCR with Wollongong TCP */
51 # include <netinet/ip.h>
55 # include <netconfig.h>
59 #if !defined(__GNU__) && !defined(__hpux) /* XXX __hpux might be wrong */
65 typedef struct _Choices
{
66 struct _Choices
*next
;
69 CARD16 connectionType
;
72 } ChoiceRec
, *ChoicePtr
;
74 static ChoicePtr choices
;
77 disposeIndirectHosts()
82 if (choices
->timeout
> now
)
83 return choices
->timeout
;
84 debug( "timing out indirect host\n" );
87 XdmcpDisposeARRAY8( &c
->client
);
88 XdmcpDisposeARRAY8( &c
->port
);
89 XdmcpDisposeARRAY8( &c
->choice
);
96 indirectChoice( ARRAY8Ptr clientAddress
, ARRAY8Ptr clientPort
,
97 CARD16 connectionType
)
101 debug( "have indirect choice?\n" );
102 for (c
= choices
; c
; c
= c
->next
)
103 if (XdmcpARRAY8Equal( clientAddress
, &c
->client
) &&
104 XdmcpARRAY8Equal( clientPort
, &c
->port
) &&
105 connectionType
== c
->connectionType
)
107 debug( c
->choice
.data
? " yes\n" : " not yet\n" );
108 return c
->choice
.data
? &c
->choice
: 0;
110 debug( " host not registered\n" );
115 checkIndirectChoice( ARRAY8Ptr clientAddress
, ARRAY8Ptr clientPort
,
116 CARD16 connectionType
)
121 debug( "checkIndirectChoice\n" );
122 for (cp
= &choices
; (c
= *cp
); cp
= &c
->next
) {
123 if (XdmcpARRAY8Equal( clientAddress
, &c
->client
) &&
124 XdmcpARRAY8Equal( clientPort
, &c
->port
) &&
125 connectionType
== c
->connectionType
)
128 if (c
->choice
.data
) {
129 XdmcpDisposeARRAY8( &c
->choice
);
130 debug( " choice already made\n" );
134 XdmcpDisposeARRAY8( &c
->port
);
135 XdmcpDisposeARRAY8( &c
->client
);
140 debug( " host not registered\n" );
145 registerIndirectChoice( ARRAY8Ptr clientAddress
, ARRAY8Ptr clientPort
,
146 CARD16 connectionType
, ARRAY8Ptr choice
)
150 debug( "registering indirect %s\n", choice
? "choice" : "client" );
151 for (cp
= &choices
; (c
= *cp
); cp
= &c
->next
) {
152 if (XdmcpARRAY8Equal( clientAddress
, &c
->client
) &&
153 XdmcpARRAY8Equal( clientPort
, &c
->port
) &&
154 connectionType
== c
->connectionType
)
160 XdmcpDisposeARRAY8( &c
->choice
);
161 debug( " replacing existing\n" );
166 if (!(c
= (ChoicePtr
)Malloc( sizeof(ChoiceRec
) )))
168 if (!XdmcpCopyARRAY8( clientAddress
, &c
->client
)) {
172 if (!XdmcpCopyARRAY8( clientPort
, &c
->port
)) {
173 XdmcpDisposeARRAY8( &c
->client
);
177 c
->connectionType
= connectionType
;
180 if (choice
&& !XdmcpCopyARRAY8( choice
, &c
->choice
)) {
181 XdmcpDisposeARRAY8( &c
->port
);
182 XdmcpDisposeARRAY8( &c
->client
);
186 c
->timeout
= now
+ choiceTimeout
;
192 /* ####################### */
195 typedef struct _HostAddr
{
196 struct _HostAddr
*next
;
197 struct sockaddr
*addr
;
202 static HostAddr
*hostAddrdb
;
204 typedef struct _HostName
{
205 struct _HostName
*next
;
206 unsigned willing
:1, alive
:1;
207 ARRAY8 hostname
, status
;
208 CARD16 connectionType
;
212 static HostName
*hostNamedb
;
214 static XdmcpBuffer directBuffer
, broadcastBuffer
;
215 static XdmcpBuffer buffer
;
218 #if defined(IPv6) && defined(AF_INET6)
219 static int socket6FD
;
228 for (hosts
= hostAddrdb
; hosts
; hosts
= hosts
->next
)
229 #if defined(IPv6) && defined(AF_INET6)
230 XdmcpFlush( hosts
->addr
->sa_family
== AF_INET6
? socket6FD
: socketFD
,
232 XdmcpFlush( socketFD
,
234 hosts
->type
== QUERY
? &directBuffer
: &broadcastBuffer
,
235 (XdmcpNetaddr
)hosts
->addr
, hosts
->addrlen
);
239 addHostname( ARRAY8Ptr hostname
, ARRAY8Ptr status
,
240 struct sockaddr
*addr
, int will
)
242 HostName
**names
, *name
;
244 CARD16 connectionType
;
246 switch (addr
->sa_family
) {
249 (CARD8
*)& ((struct sockaddr_in
*)addr
)->sin_addr
;
251 connectionType
= FamilyInternet
;
253 #if defined(IPv6) && defined(AF_INET6)
256 (CARD8
*)&((struct sockaddr_in6
*)addr
)->sin6_addr
;
257 hostAddr
.length
= 16;
258 connectionType
= FamilyInternet6
;
262 hostAddr
.data
= (CARD8
*)"";
264 connectionType
= FamilyLocal
;
267 for (names
= &hostNamedb
; *names
; names
= &(*names
)->next
) {
269 if (connectionType
== name
->connectionType
&&
270 XdmcpARRAY8Equal( &hostAddr
, &name
->hostaddr
))
272 if (XdmcpARRAY8Equal( status
, &name
->status
))
274 XdmcpDisposeARRAY8( &name
->status
);
275 XdmcpDisposeARRAY8( hostname
);
277 gSendInt( G_Ch_ChangeHost
);
281 if (!(name
= (HostName
*)Malloc( sizeof(*name
) )))
283 if (hostname
->length
) {
284 switch (addr
->sa_family
) {
286 #if defined(IPv6) && defined(AF_INET6)
290 struct hostent
*hostent
;
293 hostent
= gethostbyaddr( (char *)hostAddr
.data
,
294 hostAddr
.length
, addr
->sa_family
);
296 XdmcpDisposeARRAY8( hostname
);
297 host
= hostent
->h_name
;
298 XdmcpAllocARRAY8( hostname
, strlen( host
) );
299 memmove( hostname
->data
, host
, hostname
->length
);
304 if (!XdmcpAllocARRAY8( &name
->hostaddr
, hostAddr
.length
)) {
305 free( (char *)name
);
308 memmove( name
->hostaddr
.data
, hostAddr
.data
, hostAddr
.length
);
309 name
->connectionType
= connectionType
;
310 name
->hostname
= *hostname
;
315 gSendInt( G_Ch_AddHost
);
318 name
->willing
= will
;
319 name
->status
= *status
;
321 gSendInt( (int)(long)name
); /* just an id */
322 gSendNStr( (char *)name
->hostname
.data
, name
->hostname
.length
);
323 gSendNStr( (char *)name
->status
.data
, name
->status
.length
);
330 disposeHostname( HostName
*host
)
332 XdmcpDisposeARRAY8( &host
->hostname
);
333 XdmcpDisposeARRAY8( &host
->hostaddr
);
334 XdmcpDisposeARRAY8( &host
->status
);
335 free( (char *)host
);
339 emptyHostnames( void )
341 HostName
*host
, *nhost
;
343 for (host
= hostNamedb
; host
; host
= nhost
) {
345 disposeHostname( host
);
351 receivePacket( int sfd
)
354 ARRAY8 authenticationName
;
357 int saveHostname
= False
;
358 #if defined(IPv6) && defined(AF_INET6)
359 struct sockaddr_storage addr
;
361 struct sockaddr addr
;
365 addrlen
= sizeof(addr
);
366 if (!XdmcpFill( sfd
, &buffer
, (XdmcpNetaddr
)&addr
, &addrlen
))
368 if (!XdmcpReadHeader( &buffer
, &header
))
370 if (header
.version
!= XDM_PROTOCOL_VERSION
)
374 authenticationName
.data
= 0;
375 switch (header
.opcode
) {
377 if (XdmcpReadARRAY8( &buffer
, &authenticationName
) &&
378 XdmcpReadARRAY8( &buffer
, &hostname
) &&
379 XdmcpReadARRAY8( &buffer
, &status
)) {
380 if (header
.length
== 6 + authenticationName
.length
+
381 hostname
.length
+ status
.length
) {
382 if (addHostname( &hostname
, &status
,
383 (struct sockaddr
*)&addr
, True
))
387 XdmcpDisposeARRAY8( &authenticationName
);
390 if (XdmcpReadARRAY8( &buffer
, &hostname
) &&
391 XdmcpReadARRAY8( &buffer
, &status
)) {
392 if (header
.length
== 4 + hostname
.length
+ status
.length
) {
393 if (addHostname( &hostname
, &status
,
394 (struct sockaddr
*)&addr
, False
))
403 XdmcpDisposeARRAY8( &hostname
);
404 XdmcpDisposeARRAY8( &status
);
409 addHostaddr( HostAddr
**hosts
, struct sockaddr
*addr
, int len
, xdmOpCode type
)
413 debug( "adding host %[*hhu, type %d\n", len
, addr
, type
);
414 for (host
= *hosts
; host
; host
= host
->next
)
415 if (host
->type
== type
&& host
->addr
->sa_family
== addr
->sa_family
)
416 switch (addr
->sa_family
) {
419 struct sockaddr_in
*na
= (struct sockaddr_in
*)addr
;
420 struct sockaddr_in
*oa
= (struct sockaddr_in
*)host
->addr
;
421 if (na
->sin_port
== oa
->sin_port
&&
422 na
->sin_addr
.s_addr
== oa
->sin_addr
.s_addr
)
426 #if defined(IPv6) && defined(AF_INET6)
429 struct sockaddr_in6
*na
= (struct sockaddr_in6
*)addr
;
430 struct sockaddr_in6
*oa
= (struct sockaddr_in6
*)host
->addr
;
431 if (na
->sin6_port
== oa
->sin6_port
&&
432 !memcmp( &na
->sin6_addr
, &oa
->sin6_addr
, 16 ))
440 debug( " not dupe\n" );
441 if (!(host
= (HostAddr
*)Malloc( sizeof(*host
) )))
443 if (!(host
->addr
= (struct sockaddr
*)Malloc( len
))) {
444 free( (char *)host
);
447 memcpy( (char *)host
->addr
, (char *)addr
, len
);
455 registerHostaddr( struct sockaddr
*addr
, int len
, xdmOpCode type
)
457 addHostaddr( &hostAddrdb
, addr
, len
, type
);
461 emptyPingHosts( void )
463 HostAddr
*host
, *nhost
;
465 for (host
= hostAddrdb
; host
; host
= nhost
) {
473 /* Handle variable length ifreq in BNR2 and later */
474 #ifdef VARIABLE_IFREQ
475 # define ifr_size(p) \
476 (sizeof(struct ifreq) + \
477 (p->ifr_addr.sa_len > sizeof (p->ifr_addr) ? \
478 p->ifr_addr.sa_len - sizeof (p->ifr_addr) : 0))
480 # define ifr_size(p) (sizeof(struct ifreq))
483 #define IFC_REQ(ifc) ifc.ifc_req
485 #ifndef SYSV_SIOCGIFCONF
486 # define ifioctl ioctl
490 registerBroadcastForPing( void )
492 struct sockaddr_in in_addr
;
495 in_addr
.sin_addr
.s_addr
= htonl( 0xFFFFFFFF );
496 in_addr
.sin_port
= htons( XDM_UDP_PORT
);
497 registerHostaddr( (struct sockaddr
*)&in_addr
, sizeof(in_addr
),
501 register struct ifreq
*ifr
;
502 struct sockaddr broad_addr
;
503 char buf
[2048], *cp
, *cplim
;
504 # ifdef WINTCP /* NCR with Wollongong TCP */
510 ifcp
= (struct ifconf
*)buf
;
511 ifcp
->ifc_buf
= buf
+ 4;
512 ifcp
->ifc_len
= sizeof(buf
) - 4;
514 if ((ipfd
= open( "/dev/ip", O_RDONLY
)) < 0) {
515 t_error( "RegisterBroadcastForPing() t_open(/dev/ip) failed" );
519 ioc
.ic_cmd
= IPIOC_GETIFCONF
;
521 ioc
.ic_len
= sizeof(buf
);
522 ioc
.ic_dp
= (char *)ifcp
;
524 if (ioctl( ipfd
, (int)I_STR
, (char *)&ioc
) < 0) {
525 perror( "RegisterBroadcastForPing() ioctl(I_STR(IPIOC_GETIFCONF)) failed" );
530 for (ifr
= ifcp
->ifc_req
, n
= ifcp
->ifc_len
/ sizeof(struct ifreq
);
533 ifc
.ifc_len
= sizeof(buf
);
535 if (ifioctl(socketFD
, (int)SIOCGIFCONF
, (char *)&ifc
) < 0)
538 cplim
= (char *)IFC_REQ( ifc
) + ifc
.ifc_len
;
540 for (cp
= (char *)IFC_REQ( ifc
); cp
< cplim
; cp
+= ifr_size(ifr
))
544 ifr
= (struct ifreq
*)cp
;
546 if (ifr
->ifr_addr
.sa_family
!= AF_INET
)
549 broad_addr
= ifr
->ifr_addr
;
550 ((struct sockaddr_in
*)&broad_addr
)->sin_addr
.s_addr
=
551 htonl( INADDR_BROADCAST
);
552 # ifdef SIOCGIFBRDADDR
554 struct ifreq broad_req
;
557 # ifdef WINTCP /* NCR with Wollongong TCP */
558 ioc
.ic_cmd
= IPIOC_GETIFFLAGS
;
560 ioc
.ic_len
= sizeof(broad_req
);
561 ioc
.ic_dp
= (char *)&broad_req
;
563 if (ioctl( ipfd
, I_STR
, (char *)&ioc
)
565 if (ifioctl( socketFD
, SIOCGIFFLAGS
, (char *)&broad_req
)
568 (broad_req
.ifr_flags
& IFF_BROADCAST
) &&
569 (broad_req
.ifr_flags
& IFF_UP
))
572 # ifdef WINTCP /* NCR with Wollongong TCP */
573 ioc
.ic_cmd
= IPIOC_GETIFBRDADDR
;
575 ioc
.ic_len
= sizeof(broad_req
);
576 ioc
.ic_dp
= (char *)&broad_req
;
578 if (ioctl( ipfd
, I_STR
, (char *)&ioc
)
580 if (ifioctl( socketFD
, SIOCGIFBRDADDR
, (char *)&broad_req
)
583 broad_addr
= broad_req
.ifr_addr
;
590 in_addr
= *((struct sockaddr_in
*)&broad_addr
);
591 in_addr
.sin_port
= htons( XDM_UDP_PORT
);
592 # ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
593 in_addr
.sin_len
= sizeof(in_addr
);
595 registerHostaddr( (struct sockaddr
*)&in_addr
, sizeof(in_addr
),
602 makeSockAddrs( const char *name
, HostAddr
**hosts
)
604 #if defined(IPv6) && defined(AF_INET6)
605 struct addrinfo
*ai
, *nai
, hints
;
606 bzero( &hints
, sizeof(hints
) );
607 hints
.ai_socktype
= SOCK_DGRAM
;
608 if (getaddrinfo( name
, stringify( XDM_UDP_PORT
), &hints
, &ai
))
610 for (nai
= ai
; nai
; nai
= nai
->ai_next
)
611 if ((nai
->ai_family
== AF_INET
) || (nai
->ai_family
== AF_INET6
))
612 addHostaddr( hosts
, nai
->ai_addr
, nai
->ai_addrlen
,
613 (nai
->ai_family
== AF_INET
?
614 IN_MULTICAST( ((struct sockaddr_in
*)nai
->ai_addr
)->sin_addr
.s_addr
) :
615 IN6_IS_ADDR_MULTICAST( &((struct sockaddr_in6
*)nai
->ai_addr
)->sin6_addr
)) ?
616 BROADCAST_QUERY
: QUERY
);
618 struct sockaddr_in in_addr
;
619 /* Per RFC 1123, check first for IP address in dotted-decimal form */
620 if ((in_addr
.sin_addr
.s_addr
= inet_addr( name
)) == (unsigned)-1) {
621 struct hostent
*hostent
;
622 if (!(hostent
= gethostbyname( name
)) ||
623 hostent
->h_addrtype
!= AF_INET
)
625 memcpy( &in_addr
.sin_addr
, hostent
->h_addr
, 4 );
627 in_addr
.sin_family
= AF_INET
;
628 in_addr
.sin_port
= htons( XDM_UDP_PORT
);
629 # ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
630 in_addr
.sin_len
= sizeof(in_addr
);
632 addHostaddr( hosts
, (struct sockaddr
*)&in_addr
, sizeof(in_addr
),
634 IN_MULTICAST( in_addr
.sin_addr
.s_addr
) ?
643 * Register the address for this host.
644 * Called for interactively specified hosts.
645 * The special names "BROADCAST" and "*" look up all the broadcast
646 * addresses on the local host.
650 registerForPing( const char *name
)
652 debug( "manual host registration: %s\n", name
);
653 if (!strcmp( name
, "BROADCAST" ) || !strcmp( name
, "*" ))
654 registerBroadcastForPing();
655 else if (!makeSockAddrs( name
, &hostAddrdb
))
662 addChooserHost( CARD16 connectionType
,
664 char *closure ATTR_UNUSED
)
666 if (connectionType
== FamilyBroadcast
) {
667 registerBroadcastForPing();
670 debug( "internal host registration: %[*hhu, family %hx\n",
671 addr
->length
, addr
->data
, connectionType
);
672 if (connectionType
== FamilyInternet
) {
673 struct sockaddr_in in_addr
;
674 in_addr
.sin_family
= AF_INET
;
675 memmove( &in_addr
.sin_addr
, addr
->data
, 4 );
676 in_addr
.sin_port
= htons( XDM_UDP_PORT
);
677 #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
678 in_addr
.sin_len
= sizeof(in_addr
);
680 registerHostaddr( (struct sockaddr
*)&in_addr
, sizeof(in_addr
),
682 IN_MULTICAST( in_addr
.sin_addr
.s_addr
) ?
687 #if defined(IPv6) && defined(AF_INET6)
688 else if (connectionType
== FamilyInternet6
) {
689 struct sockaddr_in6 in6_addr
;
690 in6_addr
.sin6_family
= AF_INET6
;
691 memmove( &in6_addr
.sin6_addr
, addr
->data
, 16 );
692 in6_addr
.sin6_port
= htons( XDM_UDP_PORT
);
693 #ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
694 in6_addr
.sin6_len
= sizeof(in6_addr
);
696 registerHostaddr( (struct sockaddr
*)&in6_addr
, sizeof(in6_addr
),
697 IN6_IS_ADDR_MULTICAST( &in6_addr
.sin6_addr
) ?
698 BROADCAST_QUERY
: QUERY
);
703 static ARRAYofARRAY8 AuthenticationNames
;
707 registerAuthenticationName( char *name
, int namelen
)
710 if (!XdmcpReallocARRAYofARRAY8( &AuthenticationNames
,
711 AuthenticationNames
.length
+ 1 ))
713 authName
= &AuthenticationNames
.data
[AuthenticationNames
.length
- 1];
714 if (!XdmcpAllocARRAY8( authName
, namelen
))
716 memmove( authName
->data
, name
, namelen
);
733 header
.version
= XDM_PROTOCOL_VERSION
;
736 for (i
= 0; i
< (int)AuthenticationNames
.length
; i
++)
737 header
.length
+= 2 + AuthenticationNames
.data
[i
].length
;
740 header
.opcode
= (CARD16
)BROADCAST_QUERY
;
741 XdmcpWriteHeader( &broadcastBuffer
, &header
);
742 XdmcpWriteARRAYofARRAY8( &broadcastBuffer
, &AuthenticationNames
);
744 header
.opcode
= (CARD16
)QUERY
;
745 XdmcpWriteHeader( &directBuffer
, &header
);
746 XdmcpWriteARRAYofARRAY8( &directBuffer
, &AuthenticationNames
);
748 #if defined(STREAMSCONN)
749 if ((socketFD
= t_open( "/dev/udp", O_RDWR
, 0 )) < 0)
752 if (t_bind( socketFD
, NULL
, NULL
) < 0) {
758 * This part of the code looks contrived. It will actually fit in nicely
759 * when the CLTS part of Xtrans is implemented.
762 struct netconfig
*nconf
;
764 if ((nconf
= getnetconfigent( "udp" )) == NULL
) {
765 t_unbind( socketFD
);
770 if (netdir_options( nconf
, ND_SET_BROADCAST
, socketFD
, NULL
)) {
771 freenetconfigent( nconf
);
772 t_unbind( socketFD
);
777 freenetconfigent( nconf
);
780 if ((socketFD
= socket( AF_INET
, SOCK_DGRAM
, 0 )) < 0)
782 #if defined(IPv6) && defined(AF_INET6)
783 socket6FD
= socket( AF_INET6
, SOCK_DGRAM
, 0 );
787 if (setsockopt( socketFD
, SOL_SOCKET
, SO_BROADCAST
, (char *)&soopts
,
788 sizeof(soopts
) ) < 0)
789 perror( "setsockopt" );
796 static void ATTR_NORETURN
797 chooseHost( int hid
)
800 #if defined(IPv6) && defined(AF_INET6)
804 for (h
= hostNamedb
; h
; h
= h
->next
)
805 if ((int)(long)h
== hid
) {
806 /* XXX error handling */
808 if ((td
->displayType
& d_location
) == dLocal
) {
809 gSendInt( D_RemoteHost
);
810 #if defined(IPv6) && defined(AF_INET6)
811 switch (h
->connectionType
) {
812 case FamilyInternet6
:
813 inet_ntop( AF_INET6
, h
->hostaddr
.data
, addr
, sizeof(addr
) );
815 default: /* FamilyInternet */
816 inet_ntop( AF_INET
, h
->hostaddr
.data
, addr
, sizeof(addr
) );
821 gSendStr( inet_ntoa( *(struct in_addr
*)h
->hostaddr
.data
) );
823 sessionExit( EX_REMOTE
);
825 gSendInt( D_ChooseHost
);
826 gSendArr( td
->clientAddr
.length
, (char *)td
->clientAddr
.data
);
827 gSendArr( td
->clientPort
.length
, (char *)td
->clientPort
.data
);
828 gSendInt( td
->connectionType
);
829 gSendArr( h
->hostaddr
.length
, (char *)h
->hostaddr
.data
);
834 /* logError( "Internal error: chose unexisting host\n" ); */
836 sessionExit( EX_NORMAL
);
840 directChooseHost( const char *name
)
844 if (!makeSockAddrs( name
, &hosts
))
846 gSendInt( G_Ch_Exit
);
847 /* XXX error handling */
849 if ((td
->displayType
& d_location
) == dLocal
) {
850 gSendInt( D_RemoteHost
);
852 sessionExit( EX_REMOTE
);
854 gSendInt( D_ChooseHost
);
855 gSendArr( td
->clientAddr
.length
, (char *)td
->clientAddr
.data
);
856 gSendArr( td
->clientPort
.length
, (char *)td
->clientPort
.data
);
857 gSendInt( td
->connectionType
);
858 gSendArr( hosts
->addrlen
, (char *)hosts
->addr
);
859 sessionExit( EX_NORMAL
);
870 struct timeval
*to
, tnow
, nextPing
;
873 static int xdmcpInited
;
876 gSendInt( G_Choose
);
877 switch (cmd
= ctrlGreeterWait( True
)) {
886 sessionExit( EX_UNMANAGE_DPY
);
889 if ((td
->displayType
& d_location
) == dLocal
) {
890 /* XXX the config reader should do the lookup already */
891 for (hostp
= td
->chooserHosts
; *hostp
; hostp
++)
892 if (!registerForPing( *hostp
))
893 logError( "Unknown host %\"s specified for local chooser preload of display %s\n", *hostp
, td
->name
);
895 forEachChooserHost( &td
->clientAddr
, td
->connectionType
,
898 gSendInt( 0 ); /* entering async mode signal */
901 for (h
= hostNamedb
; h
; h
= h
->next
)
908 if (pingTry
<= PING_TRIES
) {
909 gettimeofday( &tnow
, 0 );
910 if (nextPing
.tv_sec
< tnow
.tv_sec
||
911 (nextPing
.tv_sec
== tnow
.tv_sec
&&
912 nextPing
.tv_usec
< tnow
.tv_usec
)) {
913 if (pingTry
< PING_TRIES
) {
917 gettimeofday( &tnow
, 0 );
921 for (hp
= &hostNamedb
; *hp
; )
924 disposeHostname( *hp
);
925 gSendInt( G_Ch_RemoveHost
);
926 gSendInt( (int)(long)*hp
); /* just an id */
934 tnow
.tv_sec
= nextPing
.tv_sec
- tnow
.tv_sec
;
935 tnow
.tv_usec
= nextPing
.tv_usec
- tnow
.tv_usec
;
936 if (tnow
.tv_usec
< 0) {
937 tnow
.tv_usec
+= 1000000;
943 FD_SET( grtproc
.pipe
.fd
.r
, &rfds
);
944 FD_SET( socketFD
, &rfds
);
945 #if defined(IPv6) && defined(AF_INET6)
947 FD_SET( socket6FD
, &rfds
);
949 n
= grtproc
.pipe
.fd
.r
;
952 #if defined(IPv6) && defined(AF_INET6)
956 if (select( n
+ 1, &rfds
, 0, 0, to
) > 0) {
957 if (FD_ISSET( grtproc
.pipe
.fd
.r
, &rfds
))
958 switch (cmd
= ctrlGreeterWait( False
)) {
963 case G_Ch_RegisterHost
:
965 if (!registerForPing( host
)) {
966 gSendInt( G_Ch_BadHost
);
971 case G_Ch_DirectChoice
:
973 directChooseHost( host
);
974 gSendInt( G_Ch_BadHost
);
979 chooseHost( gRecvInt() );
986 if (FD_ISSET( socketFD
, &rfds
))
987 receivePacket( socketFD
);
988 #if defined(IPv6) && defined(AF_INET6)
989 if (socket6FD
>= 0 && FD_ISSET( socket6FD
, &rfds
))
990 receivePacket( socket6FD
);