1 /* $XConsortium: xdmcp.c /main/34 1996/12/02 10:23:29 lehors $ */
2 /* $XFree86: xc/programs/Xserver/os/xdmcp.c,v 3.9 1997/01/18 06:58:04 dawes Exp $ */
4 * Copyright 1989 Network Computing Devices, Inc., Mountain View, California.
6 * Permission to use, copy, modify, and distribute this software and its
7 * documentation for any purpose and without fee is hereby granted, provided
8 * that the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of N.C.D. not be used in advertising or
11 * publicity pertaining to distribution of the software without specific,
12 * written prior permission. N.C.D. makes no representations about the
13 * suitability of this software for any purpose. It is provided "as is"
14 * without express or implied warranty.
19 /* avoid conflicting definitions */
22 #define FreeResource wFreeResource
32 #if !defined(MINIX) && !defined(WIN32)
34 #include <sys/param.h>
35 #include <sys/socket.h>
39 #include <netinet/in.h>
44 #include <net/netlib.h>
45 #include <net/gen/netdb.h>
46 #include <net/gen/udp.h>
47 #include <net/gen/udp_io.h>
49 #include <sys/ioctl.h>
59 #include "dixstruct.h"
64 #include <netconfig.h>
73 extern fd_set EnabledDevices;
74 extern fd_set AllClients;
75 extern char *defaultDisplayClass;
77 static int xdmcpSocket, sessionSocket;
78 static xdmcp_states state;
79 static struct sockaddr_in req_sockaddr;
80 static int req_socklen;
81 static CARD32 SessionID;
82 static CARD32 timeOutTime;
83 static int timeOutRtx;
84 static CARD32 defaultKeepaliveDormancy = XDM_DEF_DORMANCY;
85 static CARD32 keepaliveDormancy = XDM_DEF_DORMANCY;
86 static CARD16 DisplayNumber;
87 static xdmcp_states XDM_INIT_STATE = XDM_OFF;
89 static char *xdmAuthCookie;
92 static XdmcpBuffer buffer;
94 static struct sockaddr_in ManagerAddress;
96 static void get_xdmcp_sock(
97 #if NeedFunctionPrototypes
102 static void send_query_msg(
103 #if NeedFunctionPrototypes
108 static void recv_willing_msg(
109 #if NeedFunctionPrototypes
110 struct sockaddr_in */*from*/,
116 static void send_request_msg(
117 #if NeedFunctionPrototypes
122 static void recv_accept_msg(
123 #if NeedFunctionPrototypes
128 static void recv_decline_msg(
129 #if NeedFunctionPrototypes
134 static void send_manage_msg(
135 #if NeedFunctionPrototypes
140 static void recv_refuse_msg(
141 #if NeedFunctionPrototypes
146 static void recv_failed_msg(
147 #if NeedFunctionPrototypes
152 static void send_keepalive_msg(
153 #if NeedFunctionPrototypes
158 static void recv_alive_msg(
159 #if NeedFunctionPrototypes
165 #if NeedFunctionPrototypes
172 #if NeedFunctionPrototypes
177 static get_manager_by_name(
178 #if NeedFunctionPrototypes
185 static void receive_packet(
186 #if NeedFunctionPrototypes
192 #if NeedFunctionPrototypes
197 extern int XdmcpDeadSession(
198 #if NeedFunctionPrototypes
204 #if NeedFunctionPrototypes
210 #if NeedFunctionPrototypes
215 static void XdmcpBlockHandler(
216 #if NeedFunctionPrototypes
218 struct timeval **/*wt*/,
219 pointer /*LastSelectMask*/
223 static void XdmcpWakeupHandler(
224 #if NeedFunctionPrototypes
227 pointer /*LastSelectMask*/
231 void XdmcpRegisterManufacturerDisplayID(
232 #if NeedFunctionPrototypes
240 #if NeedFunctionPrototypes
248 static short xdm_udp_port = XDM_UDP_PORT;
249 static Bool OneSession = FALSE;
253 ErrorF("-query host-name contact named host for XDMCP\n");
254 ErrorF("-broadcast broadcast for XDMCP\n");
255 ErrorF("-indirect host-name contact named host for indirect XDMCP\n");
256 ErrorF("-port port-num UDP port number to send messages to\n");
257 ErrorF("-once Terminate server after one session\n");
258 ErrorF("-class display-class specify display class to send in manage\n");
260 ErrorF("-cookie xdm-auth-bits specify the magic cookie for XDMCP\n");
262 ErrorF("-displayID display-id manufacturer display ID for request\n");
266 XdmcpOptions(argc, argv, i)
270 if (strcmp(argv[i], "-query") == 0) {
271 get_manager_by_name(argc, argv, ++i);
272 XDM_INIT_STATE = XDM_QUERY;
276 if (strcmp(argv[i], "-broadcast") == 0) {
277 XDM_INIT_STATE = XDM_BROADCAST;
281 if (strcmp(argv[i], "-indirect") == 0) {
282 get_manager_by_name(argc, argv, ++i);
283 XDM_INIT_STATE = XDM_INDIRECT;
287 if (strcmp(argv[i], "-port") == 0) {
289 xdm_udp_port = atoi(argv[i]);
292 if (strcmp(argv[i], "-once") == 0) {
296 if (strcmp(argv[i], "-class") == 0) {
298 defaultDisplayClass = argv[i];
302 if (strcmp(argv[i], "-cookie") == 0) {
304 xdmAuthCookie = argv[i];
308 if (strcmp(argv[i], "-displayID") == 0) {
310 XdmcpRegisterManufacturerDisplayID (argv[i], strlen (argv[i]));
317 * This section is a collection of routines for
318 * registering server-specific data with the XDMCP
324 * Save all broadcast addresses away so BroadcastQuery
325 * packets get sent everywhere
328 #define MAX_BROADCAST 10
330 static struct sockaddr_in BroadcastAddresses[MAX_BROADCAST];
331 static int NumBroadcastAddresses;
334 XdmcpRegisterBroadcastAddress (addr)
335 struct sockaddr_in *addr;
337 struct sockaddr_in *bcast;
338 if (NumBroadcastAddresses >= MAX_BROADCAST)
340 bcast = &BroadcastAddresses[NumBroadcastAddresses++];
341 bzero (bcast, sizeof (struct sockaddr_in));
343 bcast->sin_len = addr->sin_len;
345 bcast->sin_family = addr->sin_family;
346 bcast->sin_port = htons (xdm_udp_port);
347 bcast->sin_addr = addr->sin_addr;
351 * Each authentication type is registered here; Validator
352 * will be called to check all access attempts using
353 * the specified authentication type
356 static ARRAYofARRAY8 AuthenticationNames, AuthenticationDatas;
357 typedef struct _AuthenticationFuncs {
361 } AuthenticationFuncsRec, *AuthenticationFuncsPtr;
363 static AuthenticationFuncsPtr AuthenticationFuncsList;
366 XdmcpRegisterAuthentication (name, namelen, data, datalen, Validator, Generator, AddAuth)
376 ARRAY8 AuthenticationName, AuthenticationData;
377 static AuthenticationFuncsPtr newFuncs;
379 if (!XdmcpAllocARRAY8 (&AuthenticationName, namelen))
381 if (!XdmcpAllocARRAY8 (&AuthenticationData, datalen))
383 XdmcpDisposeARRAY8 (&AuthenticationName);
386 for (i = 0; i < namelen; i++)
387 AuthenticationName.data[i] = name[i];
388 for (i = 0; i < datalen; i++)
389 AuthenticationData.data[i] = data[i];
390 if (!(XdmcpReallocARRAYofARRAY8 (&AuthenticationNames,
391 AuthenticationNames.length + 1) &&
392 XdmcpReallocARRAYofARRAY8 (&AuthenticationDatas,
393 AuthenticationDatas.length + 1) &&
394 (newFuncs = (AuthenticationFuncsPtr) xalloc (
395 (AuthenticationNames.length + 1) * sizeof (AuthenticationFuncsRec)))))
397 XdmcpDisposeARRAY8 (&AuthenticationName);
398 XdmcpDisposeARRAY8 (&AuthenticationData);
401 for (i = 0; i < AuthenticationNames.length - 1; i++)
402 newFuncs[i] = AuthenticationFuncsList[i];
403 newFuncs[AuthenticationNames.length-1].Validator = Validator;
404 newFuncs[AuthenticationNames.length-1].Generator = Generator;
405 newFuncs[AuthenticationNames.length-1].AddAuth = AddAuth;
406 xfree (AuthenticationFuncsList);
407 AuthenticationFuncsList = newFuncs;
408 AuthenticationNames.data[AuthenticationNames.length-1] = AuthenticationName;
409 AuthenticationDatas.data[AuthenticationDatas.length-1] = AuthenticationData;
413 * Select the authentication type to be used; this is
414 * set by the manager of the host to be connected to.
417 ARRAY8 noAuthenticationName = {(CARD16) 0, (CARD8Ptr) 0};
418 ARRAY8 noAuthenticationData = {(CARD16) 0, (CARD8Ptr) 0};
419 ARRAY8Ptr AuthenticationName = &noAuthenticationName;
420 ARRAY8Ptr AuthenticationData = &noAuthenticationData;
421 AuthenticationFuncsPtr AuthenticationFuncs;
424 XdmcpSetAuthentication (name)
429 for (i = 0; i < AuthenticationNames.length; i++)
430 if (XdmcpARRAY8Equal (&AuthenticationNames.data[i], name))
432 AuthenticationName = &AuthenticationNames.data[i];
433 AuthenticationData = &AuthenticationDatas.data[i];
434 AuthenticationFuncs = &AuthenticationFuncsList[i];
440 * Register the host address for the display
443 static ARRAY16 ConnectionTypes;
444 static ARRAYofARRAY8 ConnectionAddresses;
445 static long xdmcpGeneration;
448 XdmcpRegisterConnection (type, address, addrlen)
456 if (xdmcpGeneration != serverGeneration)
458 XdmcpDisposeARRAY16 (&ConnectionTypes);
459 XdmcpDisposeARRAYofARRAY8 (&ConnectionAddresses);
460 xdmcpGeneration = serverGeneration;
462 newAddress = (CARD8 *) xalloc (addrlen * sizeof (CARD8));
465 if (!XdmcpReallocARRAY16 (&ConnectionTypes, ConnectionTypes.length + 1))
470 if (!XdmcpReallocARRAYofARRAY8 (&ConnectionAddresses,
471 ConnectionAddresses.length + 1))
476 ConnectionTypes.data[ConnectionTypes.length - 1] = (CARD16) type;
477 for (i = 0; i < addrlen; i++)
478 newAddress[i] = address[i];
479 ConnectionAddresses.data[ConnectionAddresses.length-1].data = newAddress;
480 ConnectionAddresses.data[ConnectionAddresses.length-1].length = addrlen;
484 * Register an Authorization Name. XDMCP advertises this list
488 static ARRAYofARRAY8 AuthorizationNames;
491 XdmcpRegisterAuthorizations ()
493 XdmcpDisposeARRAYofARRAY8 (&AuthorizationNames);
494 RegisterAuthorizations ();
498 XdmcpRegisterAuthorization (name, namelen)
505 authName.data = (CARD8 *) xalloc (namelen * sizeof (CARD8));
508 if (!XdmcpReallocARRAYofARRAY8 (&AuthorizationNames, AuthorizationNames.length +1))
510 xfree (authName.data);
513 for (i = 0; i < namelen; i++)
514 authName.data[i] = (CARD8) name[i];
515 authName.length = namelen;
516 AuthorizationNames.data[AuthorizationNames.length-1] = authName;
520 * Register the DisplayClass string
526 XdmcpRegisterDisplayClass (name, length)
532 XdmcpDisposeARRAY8 (&DisplayClass);
533 if (!XdmcpAllocARRAY8 (&DisplayClass, length))
535 for (i = 0; i < length; i++)
536 DisplayClass.data[i] = (CARD8) name[i];
540 * Register the Manufacturer display ID
543 ARRAY8 ManufacturerDisplayID;
546 XdmcpRegisterManufacturerDisplayID (name, length)
552 XdmcpDisposeARRAY8 (&ManufacturerDisplayID);
553 if (!XdmcpAllocARRAY8 (&ManufacturerDisplayID, length))
555 for (i = 0; i < length; i++)
556 ManufacturerDisplayID.data[i] = (CARD8) name[i];
560 * initialize XDMCP; create the socket, compute the display
561 * number, set up the state machine
567 state = XDM_INIT_STATE;
570 XdmAuthenticationInit (xdmAuthCookie, strlen (xdmAuthCookie));
572 if (state != XDM_OFF)
574 XdmcpRegisterAuthorizations();
575 XdmcpRegisterDisplayClass (defaultDisplayClass, strlen (defaultDisplayClass));
577 RegisterBlockAndWakeupHandlers (XdmcpBlockHandler, XdmcpWakeupHandler,
580 DisplayNumber = (CARD16) atoi(display);
589 state = XDM_INIT_STATE;
590 if (state != XDM_OFF)
592 RegisterBlockAndWakeupHandlers (XdmcpBlockHandler, XdmcpWakeupHandler,
600 * Called whenever a new connection is created; notices the
601 * first connection and saves it to terminate the session
606 XdmcpOpenDisplay(sock)
609 if (state != XDM_AWAIT_MANAGE_RESPONSE)
611 state = XDM_RUN_SESSION;
612 sessionSocket = sock;
616 XdmcpCloseDisplay(sock)
619 if ((state != XDM_RUN_SESSION && state != XDM_AWAIT_ALIVE_RESPONSE)
620 || sessionSocket != sock)
622 state = XDM_INIT_STATE;
624 dispatchException |= DE_TERMINATE;
626 dispatchException |= DE_RESET;
627 isItTimeToYield = TRUE;
631 * called before going to sleep, this routine
632 * may modify the timeout value about to be sent
633 * to select; in this way XDMCP can do appropriate things
634 * dynamically while starting up
639 XdmcpBlockHandler(data, wt, pReadmask)
640 pointer data; /* unused */
644 fd_set *LastSelectMask = (fd_set*)pReadmask;
645 CARD32 millisToGo, wtMillis;
646 static struct timeval waittime;
648 if (state == XDM_OFF)
650 FD_SET(xdmcpSocket, LastSelectMask);
651 if (timeOutTime == 0)
653 millisToGo = GetTimeInMillis();
654 if (millisToGo < timeOutTime)
655 millisToGo = timeOutTime - millisToGo;
660 waittime.tv_sec = (millisToGo) / 1000;
661 waittime.tv_usec = 1000 * (millisToGo % 1000);
666 wtMillis = (*wt)->tv_sec * 1000 + (*wt)->tv_usec / 1000;
667 if (millisToGo < wtMillis)
669 (*wt)->tv_sec = (millisToGo) / 1000;
670 (*wt)->tv_usec = 1000 * (millisToGo % 1000);
676 * called after select returns; this routine will
677 * recognise when XDMCP packets await and
678 * process them appropriately
683 XdmcpWakeupHandler(data, i, pReadmask)
684 pointer data; /* unused */
688 fd_set* LastSelectMask = (fd_set*)pReadmask;
689 fd_set devicesReadable;
691 if (state == XDM_OFF)
695 if (FD_ISSET(xdmcpSocket, LastSelectMask))
698 FD_CLR(xdmcpSocket, LastSelectMask);
700 XFD_ANDSET(&devicesReadable, LastSelectMask, &EnabledDevices);
701 if (XFD_ANYSET(&devicesReadable))
703 if (state == XDM_AWAIT_USER_INPUT)
705 else if (state == XDM_RUN_SESSION)
706 keepaliveDormancy = defaultKeepaliveDormancy;
708 if (XFD_ANYSET(&AllClients) && state == XDM_RUN_SESSION)
709 timeOutTime = GetTimeInMillis() + keepaliveDormancy * 1000;
711 else if (timeOutTime && GetTimeInMillis() >= timeOutTime)
713 if (state == XDM_RUN_SESSION)
715 state = XDM_KEEPALIVE;
724 * This routine should be called from the routine that drives the
725 * user's host menu when the user selects a host
728 XdmcpSelectHost(host_sockaddr, host_len, AuthenticationName)
729 struct sockaddr_in *host_sockaddr;
731 ARRAY8Ptr AuthenticationName;
733 state = XDM_START_CONNECTION;
734 memmove(&req_sockaddr, host_sockaddr, host_len);
735 req_socklen = host_len;
736 XdmcpSetAuthentication (AuthenticationName);
741 * !!! this routine should be replaced by a routine that adds
742 * the host to the user's host menu. the current version just
743 * selects the first host to respond with willing message.
747 XdmcpAddHost(from, fromlen, AuthenticationName, hostname, status)
748 struct sockaddr_in *from;
749 ARRAY8Ptr AuthenticationName, hostname, status;
751 XdmcpSelectHost(from, fromlen, AuthenticationName);
755 * A message is queued on the socket; read it and
756 * do the appropriate thing
759 ARRAY8 UnwillingMessage = { (CARD8) 14, (CARD8 *) "Host unwilling" };
764 struct sockaddr_in from;
765 int fromlen = sizeof(struct sockaddr_in);
768 /* read message off socket */
769 if (!XdmcpFill (xdmcpSocket, &buffer, (struct sockaddr *) &from, &fromlen))
772 /* reset retransmission backoff */
775 if (!XdmcpReadHeader (&buffer, &header))
778 if (header.version != XDM_PROTOCOL_VERSION)
781 switch (header.opcode) {
783 recv_willing_msg(&from, fromlen, header.length);
786 XdmcpFatal("Manager unwilling", &UnwillingMessage);
789 recv_accept_msg(header.length);
792 recv_decline_msg(header.length);
795 recv_refuse_msg(header.length);
798 recv_failed_msg(header.length);
801 recv_alive_msg(header.length);
807 * send the appropriate message given the current state
820 case XDM_START_CONNECTION:
827 send_keepalive_msg();
830 rtx = (XDM_MIN_RTX << timeOutRtx);
831 if (rtx > XDM_MAX_RTX)
833 timeOutTime = GetTimeInMillis() + rtx * 1000;
837 * The session is declared dead for some reason; too many
838 * timeouts, or Keepalive failure.
841 XdmcpDeadSession (reason)
844 ErrorF ("XDM: %s, declaring session dead\n", reason);
845 state = XDM_INIT_STATE;
846 isItTimeToYield = TRUE;
847 dispatchException |= DE_RESET;
854 * Timeout waiting for an XDMCP response.
861 if (state == XDM_AWAIT_ALIVE_RESPONSE && timeOutRtx >= XDM_KA_RTX_LIMIT )
863 XdmcpDeadSession ("too many keepalive retransmissions");
866 else if (timeOutRtx >= XDM_RTX_LIMIT)
868 ErrorF("XDM: too many retransmissions\n");
869 state = XDM_AWAIT_USER_INPUT;
876 case XDM_COLLECT_QUERY:
879 case XDM_COLLECT_BROADCAST_QUERY:
880 state = XDM_BROADCAST;
882 case XDM_COLLECT_INDIRECT_QUERY:
883 state = XDM_INDIRECT;
885 case XDM_AWAIT_REQUEST_RESPONSE:
886 state = XDM_START_CONNECTION;
888 case XDM_AWAIT_MANAGE_RESPONSE:
891 case XDM_AWAIT_ALIVE_RESPONSE:
892 state = XDM_KEEPALIVE;
901 state = XDM_INIT_STATE;
906 XdmcpCheckAuthentication (Name, Data, packet_type)
907 ARRAY8Ptr Name, Data;
910 return (XdmcpARRAY8Equal (Name, AuthenticationName) &&
911 (AuthenticationName->length == 0 ||
912 (*AuthenticationFuncs->Validator) (AuthenticationData, Data, packet_type)));
915 XdmcpAddAuthorization (name, data)
916 ARRAY8Ptr name, data;
918 Bool (*AddAuth)(), AddAuthorization();
920 if (AuthenticationFuncs && AuthenticationFuncs->AddAuth)
921 AddAuth = AuthenticationFuncs->AddAuth;
923 AddAuth = AddAuthorization;
924 return (*AddAuth) ((unsigned short)name->length,
926 (unsigned short)data->length,
931 * from here to the end of this file are routines private
932 * to the state machine.
939 struct netconfig *nconf;
941 if ((xdmcpSocket = t_open("/dev/udp", O_RDWR, 0)) < 0) {
942 XdmcpWarning("t_open() of /dev/udp failed");
946 if( t_bind(xdmcpSocket,NULL,NULL) < 0 ) {
947 XdmcpWarning("UDP socket creation failed");
948 t_error("t_bind(xdmcpSocket) failed" );
949 t_close(xdmcpSocket);
954 * This part of the code looks contrived. It will actually fit in nicely
955 * when the CLTS part of Xtrans is implemented.
958 if( (nconf=getnetconfigent("udp")) == NULL ) {
959 XdmcpWarning("UDP socket creation failed: getnetconfigent()");
960 t_unbind(xdmcpSocket);
961 t_close(xdmcpSocket);
965 if( netdir_options(nconf, ND_SET_BROADCAST, xdmcpSocket, NULL) ) {
966 XdmcpWarning("UDP set broadcast option failed: netdir_options()");
967 freenetconfigent(nconf);
968 t_unbind(xdmcpSocket);
969 t_close(xdmcpSocket);
973 freenetconfigent(nconf);
978 if ((xdmcpSocket = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
982 nwio_udpopt_t udpopt;
985 udp_device= getenv("UDP_DEVICE");
986 if (udp_device == NULL)
987 udp_device= UDP_DEVICE;
988 xdmcpSocket= open(udp_device, O_RDWR);
989 if (xdmcpSocket != -1)
991 udpopt.nwuo_flags= NWUO_COPY | NWUO_LP_SEL | NWUO_EN_LOC |
992 NWUO_DI_BROAD | NWUO_RP_ANY | NWUO_RA_ANY | NWUO_RWDATALL |
994 r= ioctl(xdmcpSocket, NWIOSUDPOPT, &udpopt);
1002 ioctl(xdmcpSocket, NWIOGUDPOPT, &udpopt);
1003 ErrorF("0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n",
1005 udpopt.nwuo_locport,
1006 udpopt.nwuo_remport,
1007 udpopt.nwuo_locaddr,
1008 udpopt.nwuo_remaddr);
1010 if (xdmcpSocket != -1)
1012 fcntl(xdmcpSocket, F_SETFD, fcntl(xdmcpSocket, F_GETFD) |
1014 nbio_register(xdmcpSocket);
1015 ref.ref_int= xdmcpSocket;
1016 nbio_setcallback(xdmcpSocket, ASIO_READ, read_cb, ref);
1018 if (xdmcpSocket == -1)
1020 XdmcpWarning("UDP socket creation failed");
1022 else if (setsockopt(xdmcpSocket, SOL_SOCKET, SO_BROADCAST, (char *)&soopts,
1023 sizeof(soopts)) < 0)
1024 XdmcpWarning("UDP set broadcast socket-option failed");
1025 #endif /* SO_BROADCAST */
1026 #endif /* STREAMSCONN */
1033 Bool broadcast = FALSE;
1036 header.version = XDM_PROTOCOL_VERSION;
1039 header.opcode = (CARD16) QUERY;
1040 state = XDM_COLLECT_QUERY;
1043 header.opcode = (CARD16) BROADCAST_QUERY;
1044 state = XDM_COLLECT_BROADCAST_QUERY;
1048 header.opcode = (CARD16) INDIRECT_QUERY;
1049 state = XDM_COLLECT_INDIRECT_QUERY;
1053 for (i = 0; i < AuthenticationNames.length; i++)
1054 header.length += 2 + AuthenticationNames.data[i].length;
1056 XdmcpWriteHeader (&buffer, &header);
1057 XdmcpWriteARRAYofARRAY8 (&buffer, &AuthenticationNames);
1062 for (i = 0; i < NumBroadcastAddresses; i++)
1063 XdmcpFlush (xdmcpSocket, &buffer, &BroadcastAddresses[i],
1064 sizeof (struct sockaddr_in));
1068 XdmcpFlush (xdmcpSocket, &buffer, &ManagerAddress,
1069 sizeof (ManagerAddress));
1074 recv_willing_msg(from, fromlen, length)
1075 struct sockaddr_in *from;
1079 ARRAY8 authenticationName;
1083 authenticationName.data = 0;
1086 if (XdmcpReadARRAY8 (&buffer, &authenticationName) &&
1087 XdmcpReadARRAY8 (&buffer, &hostname) &&
1088 XdmcpReadARRAY8 (&buffer, &status))
1090 if (length == 6 + authenticationName.length +
1091 hostname.length + status.length)
1095 case XDM_COLLECT_QUERY:
1096 XdmcpSelectHost(from, fromlen, &authenticationName);
1098 case XDM_COLLECT_BROADCAST_QUERY:
1099 case XDM_COLLECT_INDIRECT_QUERY:
1100 XdmcpAddHost(from, fromlen, &authenticationName, &hostname, &status);
1105 XdmcpDisposeARRAY8 (&authenticationName);
1106 XdmcpDisposeARRAY8 (&hostname);
1107 XdmcpDisposeARRAY8 (&status);
1116 ARRAY8 authenticationData;
1118 header.version = XDM_PROTOCOL_VERSION;
1119 header.opcode = (CARD16) REQUEST;
1121 length = 2; /* display number */
1122 length += 1 + 2 * ConnectionTypes.length; /* connection types */
1123 length += 1; /* connection addresses */
1124 for (i = 0; i < ConnectionAddresses.length; i++)
1125 length += 2 + ConnectionAddresses.data[i].length;
1126 authenticationData.length = 0;
1127 authenticationData.data = 0;
1128 if (AuthenticationFuncs)
1130 (*AuthenticationFuncs->Generator) (AuthenticationData,
1131 &authenticationData,
1134 length += 2 + AuthenticationName->length; /* authentication name */
1135 length += 2 + authenticationData.length; /* authentication data */
1136 length += 1; /* authorization names */
1137 for (i = 0; i < AuthorizationNames.length; i++)
1138 length += 2 + AuthorizationNames.data[i].length;
1139 length += 2 + ManufacturerDisplayID.length; /* display ID */
1140 header.length = length;
1142 if (!XdmcpWriteHeader (&buffer, &header))
1144 XdmcpDisposeARRAY8 (&authenticationData);
1147 XdmcpWriteCARD16 (&buffer, DisplayNumber);
1148 XdmcpWriteARRAY16 (&buffer, &ConnectionTypes);
1149 XdmcpWriteARRAYofARRAY8 (&buffer, &ConnectionAddresses);
1151 XdmcpWriteARRAY8 (&buffer, AuthenticationName);
1152 XdmcpWriteARRAY8 (&buffer, &authenticationData);
1153 XdmcpDisposeARRAY8 (&authenticationData);
1154 XdmcpWriteARRAYofARRAY8 (&buffer, &AuthorizationNames);
1155 XdmcpWriteARRAY8 (&buffer, &ManufacturerDisplayID);
1156 if (XdmcpFlush (xdmcpSocket, &buffer, &req_sockaddr, req_socklen))
1157 state = XDM_AWAIT_REQUEST_RESPONSE;
1161 recv_accept_msg(length)
1164 CARD32 AcceptSessionID;
1165 ARRAY8 AcceptAuthenticationName, AcceptAuthenticationData;
1166 ARRAY8 AcceptAuthorizationName, AcceptAuthorizationData;
1168 if (state != XDM_AWAIT_REQUEST_RESPONSE)
1170 AcceptAuthenticationName.data = 0;
1171 AcceptAuthenticationData.data = 0;
1172 AcceptAuthorizationName.data = 0;
1173 AcceptAuthorizationData.data = 0;
1174 if (XdmcpReadCARD32 (&buffer, &AcceptSessionID) &&
1175 XdmcpReadARRAY8 (&buffer, &AcceptAuthenticationName) &&
1176 XdmcpReadARRAY8 (&buffer, &AcceptAuthenticationData) &&
1177 XdmcpReadARRAY8 (&buffer, &AcceptAuthorizationName) &&
1178 XdmcpReadARRAY8 (&buffer, &AcceptAuthorizationData))
1180 if (length == 12 + AcceptAuthenticationName.length +
1181 AcceptAuthenticationData.length +
1182 AcceptAuthorizationName.length +
1183 AcceptAuthorizationData.length)
1185 if (!XdmcpCheckAuthentication (&AcceptAuthenticationName,
1186 &AcceptAuthenticationData, ACCEPT))
1188 XdmcpFatal ("Authentication Failure", &AcceptAuthenticationName);
1190 /* permit access control manipulations from this host */
1191 AugmentSelf (&req_sockaddr, req_socklen);
1192 /* if the authorization specified in the packet fails
1193 * to be acceptable, enable the local addresses
1195 if (!XdmcpAddAuthorization (&AcceptAuthorizationName,
1196 &AcceptAuthorizationData))
1200 SessionID = AcceptSessionID;
1205 XdmcpDisposeARRAY8 (&AcceptAuthenticationName);
1206 XdmcpDisposeARRAY8 (&AcceptAuthenticationData);
1207 XdmcpDisposeARRAY8 (&AcceptAuthorizationName);
1208 XdmcpDisposeARRAY8 (&AcceptAuthorizationData);
1212 recv_decline_msg(length)
1215 ARRAY8 status, DeclineAuthenticationName, DeclineAuthenticationData;
1218 DeclineAuthenticationName.data = 0;
1219 DeclineAuthenticationData.data = 0;
1220 if (XdmcpReadARRAY8 (&buffer, &status) &&
1221 XdmcpReadARRAY8 (&buffer, &DeclineAuthenticationName) &&
1222 XdmcpReadARRAY8 (&buffer, &DeclineAuthenticationData))
1224 if (length == 6 + status.length +
1225 DeclineAuthenticationName.length +
1226 DeclineAuthenticationData.length &&
1227 XdmcpCheckAuthentication (&DeclineAuthenticationName,
1228 &DeclineAuthenticationData, DECLINE))
1230 XdmcpFatal ("Session declined", &status);
1233 XdmcpDisposeARRAY8 (&status);
1234 XdmcpDisposeARRAY8 (&DeclineAuthenticationName);
1235 XdmcpDisposeARRAY8 (&DeclineAuthenticationData);
1243 header.version = XDM_PROTOCOL_VERSION;
1244 header.opcode = (CARD16) MANAGE;
1245 header.length = 8 + DisplayClass.length;
1247 if (!XdmcpWriteHeader (&buffer, &header))
1249 XdmcpWriteCARD32 (&buffer, SessionID);
1250 XdmcpWriteCARD16 (&buffer, DisplayNumber);
1251 XdmcpWriteARRAY8 (&buffer, &DisplayClass);
1252 state = XDM_AWAIT_MANAGE_RESPONSE;
1253 XdmcpFlush (xdmcpSocket, &buffer, &req_sockaddr, req_socklen);
1257 recv_refuse_msg(length)
1260 CARD32 RefusedSessionID;
1262 if (state != XDM_AWAIT_MANAGE_RESPONSE)
1266 if (XdmcpReadCARD32 (&buffer, &RefusedSessionID))
1268 if (RefusedSessionID == SessionID)
1270 state = XDM_START_CONNECTION;
1277 recv_failed_msg(length)
1280 CARD32 FailedSessionID;
1283 if (state != XDM_AWAIT_MANAGE_RESPONSE)
1286 if (XdmcpReadCARD32 (&buffer, &FailedSessionID) &&
1287 XdmcpReadARRAY8 (&buffer, &status))
1289 if (length == 6 + status.length &&
1290 SessionID == FailedSessionID)
1292 XdmcpFatal ("Session failed", &status);
1295 XdmcpDisposeARRAY8 (&status);
1299 send_keepalive_msg()
1303 header.version = XDM_PROTOCOL_VERSION;
1304 header.opcode = (CARD16) KEEPALIVE;
1307 XdmcpWriteHeader (&buffer, &header);
1308 XdmcpWriteCARD16 (&buffer, DisplayNumber);
1309 XdmcpWriteCARD32 (&buffer, SessionID);
1311 state = XDM_AWAIT_ALIVE_RESPONSE;
1312 XdmcpFlush (xdmcpSocket, &buffer, &req_sockaddr, req_socklen);
1316 recv_alive_msg (length)
1319 CARD8 SessionRunning;
1320 CARD32 AliveSessionID;
1323 if (state != XDM_AWAIT_ALIVE_RESPONSE)
1327 if (XdmcpReadCARD8 (&buffer, &SessionRunning) &&
1328 XdmcpReadCARD32 (&buffer, &AliveSessionID))
1330 if (SessionRunning && AliveSessionID == SessionID)
1332 /* backoff dormancy period */
1333 state = XDM_RUN_SESSION;
1334 if ((GetTimeInMillis() - lastDeviceEventTime.milliseconds) >
1335 keepaliveDormancy * 1000)
1337 keepaliveDormancy <<= 1;
1338 if (keepaliveDormancy > XDM_MAX_DORMANCY)
1339 keepaliveDormancy = XDM_MAX_DORMANCY;
1341 timeOutTime = GetTimeInMillis() + keepaliveDormancy * 1000;
1345 XdmcpDeadSession ("Alive respose indicates session dead");
1351 XdmcpFatal (type, status)
1355 FatalError ("XDMCP fatal error: %s %*.*s\n", type,
1356 status->length, status->length, status->data);
1363 ErrorF("XDMCP warning: %s\n", str);
1367 get_manager_by_name(argc, argv, i)
1371 struct hostent *hep;
1375 ErrorF("Xserver: missing host name in command line\n");
1378 if (!(hep = gethostbyname(argv[i])))
1380 ErrorF("Xserver: unknown host: %s\n", argv[i]);
1384 if (hep->h_length == sizeof (struct in_addr))
1386 if (hep->h_length == sizeof (ipaddr_t))
1389 memmove(&ManagerAddress.sin_addr, hep->h_addr, hep->h_length);
1391 ManagerAddress.sin_len = sizeof(ManagerAddress);
1393 ManagerAddress.sin_family = AF_INET;
1394 ManagerAddress.sin_port = htons (xdm_udp_port);
1398 ErrorF ("Xserver: host on strange network %s\n", argv[i]);
1404 static char read_buffer[XDM_MAX_MSGLEN+sizeof(udp_io_hdr_t)];
1405 static int read_inprogress;
1406 static int read_size;
1409 XdmcpFill (fd, buffer, from, fromlen)
1411 XdmcpBufferPtr buffer;
1412 XdmcpNetaddr from; /* return */
1413 int *fromlen; /* return */
1417 if (read_inprogress)
1424 return MNX_XdmcpFill(fd, buffer, from, fromlen, read_buffer,
1428 r= read(fd, read_buffer, sizeof(read_buffer));
1431 return MNX_XdmcpFill(fd, buffer, from, fromlen, read_buffer,
1434 else if (r == -1 && errno == EINPROGRESS)
1437 nbio_inprogress(fd, ASIO_READ, 1 /* read */, 0 /* write */,
1442 FatalError("XdmcpFill: read failed: %s\n",
1443 r == 0 ? "EOF" : strerror(errno));
1447 static void read_cb(ref, res, err)
1454 FatalError("xdmcp'read_cb: read failed: %s\n",
1455 res == 0 ? "EOF" : strerror(err));
1463 static int xdmcp_non_empty; /* avoid complaint by ranlib */