1 /* $TOG: xdmcp.c /main/5 1998/04/06 13:36:04 mgreess $ */
2 /* (c) Copyright 1997 The Open Group */
4 * (c) Copyright 1993, 1994 Hewlett-Packard Company *
5 * (c) Copyright 1993, 1994 International Business Machines Corp. *
6 * (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
7 * (c) Copyright 1993, 1994 Novell, Inc. *
16 * Revision 1.1.2.3 1995/06/06 20:25:54 Chris_Beute
17 * Code snapshot merge from March 15 and SIA changes
18 * [1995/05/31 20:17:42 Chris_Beute]
20 * Revision 1.1.2.2 1995/04/21 13:05:47 Peter_Derr
21 * dtlogin auth key fixes from deltacde
22 * [1995/04/14 18:03:44 Peter_Derr]
24 * Merge in dtlogin changes to WaitForSomething() to support command
26 * [1995/04/14 17:40:05 Peter_Derr]
28 * Use R6 xdm code to handle XDMCP
29 * [1995/04/10 19:24:11 Peter_Derr]
35 Copyright (c) 1988 X Consortium
37 Permission is hereby granted, free of charge, to any person obtaining
38 a copy of this software and associated documentation files (the
39 "Software"), to deal in the Software without restriction, including
40 without limitation the rights to use, copy, modify, merge, publish,
41 distribute, sublicense, and/or sell copies of the Software, and to
42 permit persons to whom the Software is furnished to do so, subject to
43 the following conditions:
45 The above copyright notice and this permission notice shall be included
46 in all copies or substantial portions of the Software.
48 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
49 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
50 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
51 IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
52 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
53 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
54 OTHER DEALINGS IN THE SOFTWARE.
56 Except as contained in this notice, the name of the X Consortium shall
57 not be used in advertising or otherwise to promote the sale, use or
58 other dealings in this Software without prior written authorization
59 from the X Consortium.
64 * xdm - display manager daemon
65 * Author: Keith Packard, MIT X Consortium
67 * xdmcp.c - Support for XDMCP
73 # include <X11/Xfuncs.h>
74 # include <sys/types.h>
77 #include <sys/socket.h>
78 #include <netinet/in.h>
84 extern Time_t time ();
90 #define getString(name,len) ((name = malloc (len + 1)) ? 1 : 0)
93 * interface to policy routines
96 extern ARRAY8Ptr ChooseAuthentication ();
97 extern int SelectConnectionTypeIndex ();
102 FD_TYPE WellKnownSocketsMask;
103 int WellKnownSocketsMax;
105 #define pS(s) ((s) ? ((char *) (s)) : "empty string")
107 void DestroyWellKnownSockets ()
121 AnyWellKnownSockets ()
123 return xdmcpFd != -1 || chooserFd != -1;
126 static XdmcpBuffer buffer;
130 sendForward (connectionType, address, closure)
131 CARD16 connectionType;
136 struct sockaddr_in in_addr;
140 struct sockaddr *addr;
143 switch (connectionType)
147 addr = (struct sockaddr *) &in_addr;
148 bzero ((char *) &in_addr, sizeof (in_addr));
150 in_addr.sin_len = sizeof(in_addr);
152 in_addr.sin_family = AF_INET;
153 in_addr.sin_port = htons ((short) XDM_UDP_PORT);
154 if (address->length != 4)
156 memmove( (char *) &in_addr.sin_addr, address->data, address->length);
157 addrlen = sizeof (struct sockaddr_in);
166 XdmcpFlush (xdmcpFd, &buffer, addr, addrlen);
170 extern char *NetaddrAddress();
171 extern char *NetaddrPort();
174 ClientAddress (from, addr, port, type)
175 struct sockaddr *from;
176 ARRAY8Ptr addr, port; /* return */
177 CARD16 *type; /* return */
182 data = NetaddrPort(from, &length);
183 XdmcpAllocARRAY8 (port, length);
184 memmove( port->data, data, length);
185 port->length = length;
187 family = ConvertAddr((char *)from, &length, &data);
189 XdmcpAllocARRAY8 (addr, length);
190 memmove( addr->data, data, length);
191 addr->length = length;
197 all_query_respond (from, fromlen, authenticationNames, type)
198 struct sockaddr *from;
200 ARRAYofARRAY8Ptr authenticationNames;
203 ARRAY8Ptr authenticationName;
206 CARD16 connectionType;
210 family = ConvertAddr((char *)from, &length, (char **) &(addr.data));
212 addr.length = length; /* convert int to short */
213 Debug ("all_query_respond: conntype=%d, addr=%lx, len=%d\n",
214 family, *(addr.data), addr.length);
217 connectionType = family;
219 if (type == INDIRECT_QUERY)
220 RememberIndirectClient (&addr, connectionType);
222 ForgetIndirectClient (&addr, connectionType);
224 authenticationName = ChooseAuthentication (authenticationNames);
225 if (Willing (&addr, connectionType, authenticationName, &status, type))
226 send_willing (from, fromlen, authenticationName, &status);
229 send_unwilling (from, fromlen, authenticationName, &status);
230 XdmcpDisposeARRAY8 (&status);
234 indirect_respond (from, fromlen, length)
235 struct sockaddr *from;
239 ARRAYofARRAY8 queryAuthenticationNames;
240 ARRAY8 clientAddress;
242 CARD16 connectionType;
248 Debug ("Indirect respond %d\n", length);
249 if (!XdmcpReadARRAYofARRAY8 (&buffer, &queryAuthenticationNames))
252 for (i = 0; i < (int)queryAuthenticationNames.length; i++)
253 expectedLen += 2 + queryAuthenticationNames.data[i].length;
254 if (length == expectedLen)
256 ClientAddress (from, &clientAddress, &clientPort, &connectionType);
258 * set up the forward query packet
260 header.version = XDM_PROTOCOL_VERSION;
261 header.opcode = (CARD16) FORWARD_QUERY;
263 header.length += 2 + clientAddress.length;
264 header.length += 2 + clientPort.length;
266 for (i = 0; i < (int)queryAuthenticationNames.length; i++)
267 header.length += 2 + queryAuthenticationNames.data[i].length;
268 XdmcpWriteHeader (&buffer, &header);
269 XdmcpWriteARRAY8 (&buffer, &clientAddress);
270 XdmcpWriteARRAY8 (&buffer, &clientPort);
271 XdmcpWriteARRAYofARRAY8 (&buffer, &queryAuthenticationNames);
273 localHostAsWell = ForEachMatchingIndirectHost (&clientAddress, connectionType, sendForward, (char *) 0);
275 XdmcpDisposeARRAY8 (&clientAddress);
276 XdmcpDisposeARRAY8 (&clientPort);
278 all_query_respond (from, fromlen, &queryAuthenticationNames,
283 Debug ("Indirect length error got %d expect %d\n", length, expectedLen);
285 XdmcpDisposeARRAYofARRAY8 (&queryAuthenticationNames);
289 ProcessRequestSocket ()
292 struct sockaddr_in addr;
293 int addrlen = sizeof addr;
295 Debug ("ProcessRequestSocket\n");
296 bzero ((char *) &addr, sizeof (addr));
297 if (!XdmcpFill (xdmcpFd, &buffer, &addr, &addrlen)) {
298 Debug ("XdmcpFill failed\n");
301 if (!XdmcpReadHeader (&buffer, &header)) {
302 Debug ("XdmcpReadHeader failed\n");
305 if (header.version != XDM_PROTOCOL_VERSION) {
306 Debug ("XDMCP header version read was %d, expected %d\n",
307 header.version, XDM_PROTOCOL_VERSION);
310 Debug ("header: %d %d %d\n", header.version, header.opcode, header.length);
311 switch (header.opcode)
313 case BROADCAST_QUERY:
314 broadcast_respond (&addr, addrlen, header.length);
317 query_respond (&addr, addrlen, header.length);
320 indirect_respond (&addr, addrlen, header.length);
323 forward_respond (&addr, addrlen, header.length);
326 request_respond (&addr, addrlen, header.length);
329 manage (&addr, addrlen, header.length);
332 send_alive (&addr, addrlen, header.length);
338 * dtlogin changes to WaitForSomething () merged in to support command line
341 void WaitForSomething ()
344 struct timeval timeout, *ptimeout;
346 extern int Rescan, ChildReady, wakeupTime;
348 Debug ("WaitForSomething\n");
349 if (AnyWellKnownSockets () && !ChildReady || wakeupTime > 0 ) {
350 reads = WellKnownSocketsMask;
352 if (wakeupTime >= 0 ) {
353 timeout.tv_sec = wakeupTime;
354 timeout.tv_usec = 10;
356 Debug("Setting timer on select() for %d seconds.\n", wakeupTime);
362 nready = select (WellKnownSocketsMax + 1, (int *) &reads, 0, 0, ptimeout);
364 nready = select (WellKnownSocketsMax + 1, &reads, 0, 0, ptimeout);
366 Debug ("select returns %d. Rescan: %d ChildReady: %d\n",
367 nready, Rescan, ChildReady);
370 if (xdmcpFd >= 0 && FD_ISSET (xdmcpFd, &reads))
371 ProcessRequestSocket ();
372 if (chooserFd >= 0 && FD_ISSET (chooserFd, &reads))
373 ProcessChooserSocket (chooserFd);
386 * respond to a request on the UDP socket.
389 static ARRAY8 Hostname;
392 registerHostname (name, namelen)
398 if (!XdmcpReallocARRAY8 (&Hostname, namelen))
400 for (i = 0; i < namelen; i++)
401 Hostname.data[i] = name[i];
405 direct_query_respond (from, fromlen, length, type)
406 struct sockaddr *from;
411 ARRAYofARRAY8 queryAuthenticationNames;
415 if (!XdmcpReadARRAYofARRAY8 (&buffer, &queryAuthenticationNames))
418 for (i = 0; i < (int)queryAuthenticationNames.length; i++)
419 expectedLen += 2 + queryAuthenticationNames.data[i].length;
420 if (length == expectedLen)
421 all_query_respond (from, fromlen, &queryAuthenticationNames, type);
422 XdmcpDisposeARRAYofARRAY8 (&queryAuthenticationNames);
425 query_respond (from, fromlen, length)
426 struct sockaddr *from;
430 Debug ("Query respond %d\n", length);
431 direct_query_respond (from, fromlen, length, QUERY);
434 broadcast_respond (from, fromlen, length)
435 struct sockaddr *from;
439 direct_query_respond (from, fromlen, length, BROADCAST_QUERY);
442 /* computes an X display name */
445 NetworkAddressToName(connectionType, connectionAddress, displayNumber)
446 #if NeedWidePrototypes
449 CARD16 connectionType;
451 ARRAY8Ptr connectionAddress;
452 #if NeedWidePrototypes
455 CARD16 displayNumber;
458 switch (connectionType)
463 struct hostent *hostent;
465 char *localhost, *localHostname();
467 data = connectionAddress->data;
468 hostent = gethostbyaddr ((char *)data,
469 connectionAddress->length, AF_INET);
471 localhost = localHostname ();
474 * protect against bogus host names
476 if (hostent && hostent->h_name && hostent->h_name[0]
477 && (hostent->h_name[0] != '.'))
479 if (!strcmp (localhost, hostent->h_name))
481 if (!getString (name, 10))
483 sprintf (name, ":%d", displayNumber);
487 if (removeDomainname)
489 char *localDot, *remoteDot;
491 /* check for a common domain name. This
492 * could reduce names by recognising common
493 * super-domain names as well, but I don't think
494 * this is as useful, and will confuse more
497 if ((localDot = strchr(localhost, '.')) &&
498 (remoteDot = strchr(hostent->h_name, '.')))
500 /* smash the name in place; it won't
503 if (!strcmp (localDot+1, remoteDot+1))
508 if (!getString (name, strlen (hostent->h_name) + 10))
510 sprintf (name, "%s:%d", hostent->h_name, displayNumber);
515 if (!getString (name, 25))
517 sprintf(name, "%d.%d.%d.%d:%d",
518 data[0], data[1], data[2], data[3], displayNumber);
532 forward_respond (from, fromlen, length)
533 struct sockaddr *from;
537 ARRAY8 clientAddress;
539 ARRAYofARRAY8 authenticationNames;
540 struct sockaddr *client;
545 Debug ("Forward respond %d\n", length);
546 clientAddress.length = 0;
547 clientAddress.data = 0;
548 clientPort.length = 0;
550 authenticationNames.length = 0;
551 authenticationNames.data = 0;
552 if (XdmcpReadARRAY8 (&buffer, &clientAddress) &&
553 XdmcpReadARRAY8 (&buffer, &clientPort) &&
554 XdmcpReadARRAYofARRAY8 (&buffer, &authenticationNames))
557 expectedLen += 2 + clientAddress.length;
558 expectedLen += 2 + clientPort.length;
559 expectedLen += 1; /* authenticationNames */
560 for (i = 0; i < (int)authenticationNames.length; i++)
561 expectedLen += 2 + authenticationNames.data[i].length;
562 if (length == expectedLen)
567 for (i = 0; i < (int)clientPort.length; i++)
568 j = j * 256 + clientPort.data[i];
569 Debug ("Forward client address (port %d)", j);
570 for (i = 0; i < (int)clientAddress.length; i++)
571 Debug (" %d", clientAddress.data[i]);
573 switch (from->sa_family)
578 struct sockaddr_in in_addr;
580 if (clientAddress.length != 4 ||
581 clientPort.length != 2)
585 bzero ((char *) &in_addr, sizeof (in_addr));
587 in_addr.sin_len = sizeof(in_addr);
589 in_addr.sin_family = AF_INET;
590 memmove( &in_addr.sin_addr, clientAddress.data, 4);
591 memmove( (char *) &in_addr.sin_port, clientPort.data, 2);
592 client = (struct sockaddr *) &in_addr;
593 clientlen = sizeof (in_addr);
600 struct sockaddr_un un_addr;
602 if (clientAddress.length >= sizeof (un_addr.sun_path))
604 bzero ((char *) &un_addr, sizeof (un_addr));
605 un_addr.sun_family = AF_UNIX;
606 memmove( un_addr.sun_path, clientAddress.data, clientAddress.length);
607 un_addr.sun_path[clientAddress.length] = '\0';
608 client = (struct sockaddr *) &un_addr;
610 un_addr.sun_len = strlen(un_addr.sun_path);
611 clientlen = SUN_LEN(&un_addr);
613 clientlen = sizeof (un_addr);
627 all_query_respond (client, clientlen, &authenticationNames,
632 Debug ("Forward length error got %d expect %d\n", length, expectedLen);
636 XdmcpDisposeARRAY8 (&clientAddress);
637 XdmcpDisposeARRAY8 (&clientPort);
638 XdmcpDisposeARRAYofARRAY8 (&authenticationNames);
641 send_willing (from, fromlen, authenticationName, status)
642 struct sockaddr *from;
644 ARRAY8Ptr authenticationName;
649 Debug ("Send willing %*.*s %*.*s\n", authenticationName->length,
650 authenticationName->length,
651 pS(authenticationName->data),
655 header.version = XDM_PROTOCOL_VERSION;
656 header.opcode = (CARD16) WILLING;
657 header.length = 6 + authenticationName->length +
658 Hostname.length + status->length;
659 XdmcpWriteHeader (&buffer, &header);
660 XdmcpWriteARRAY8 (&buffer, authenticationName);
661 XdmcpWriteARRAY8 (&buffer, &Hostname);
662 XdmcpWriteARRAY8 (&buffer, status);
663 XdmcpFlush (xdmcpFd, &buffer, from, fromlen);
666 send_unwilling (from, fromlen, authenticationName, status)
667 struct sockaddr *from;
669 ARRAY8Ptr authenticationName;
674 Debug ("Send unwilling %*.*s %*.*s\n", authenticationName->length,
675 authenticationName->length,
676 pS(authenticationName->data),
680 header.version = XDM_PROTOCOL_VERSION;
681 header.opcode = (CARD16) UNWILLING;
682 header.length = 4 + Hostname.length + status->length;
683 XdmcpWriteHeader (&buffer, &header);
684 XdmcpWriteARRAY8 (&buffer, &Hostname);
685 XdmcpWriteARRAY8 (&buffer, status);
686 XdmcpFlush (xdmcpFd, &buffer, from, fromlen);
689 static unsigned long globalSessionID;
691 #define NextSessionID() (++globalSessionID)
693 void init_session_id()
695 /* Set randomly so we are unlikely to reuse id's from a previous
696 * incarnation so we don't say "Alive" to those displays.
697 * Start with low digits 0 to make debugging easier.
699 globalSessionID = (time((Time_t)0)&0x7fff) * 16000;
702 static ARRAY8 outOfMemory = { (CARD16) 13, (CARD8Ptr) "Out of memory" };
703 static ARRAY8 noValidAddr = { (CARD16) 16, (CARD8Ptr) "No valid address" };
704 static ARRAY8 noValidAuth = { (CARD16) 22, (CARD8Ptr) "No valid authorization" };
705 static ARRAY8 noAuthentic = { (CARD16) 29, (CARD8Ptr) "XDM has no authentication key" };
707 request_respond (from, fromlen, length)
708 struct sockaddr *from;
712 CARD16 displayNumber;
713 ARRAY16 connectionTypes;
714 ARRAYofARRAY8 connectionAddresses;
715 ARRAY8 authenticationName;
716 ARRAY8 authenticationData;
717 ARRAYofARRAY8 authorizationNames;
718 ARRAY8 manufacturerDisplayID;
722 struct protoDisplay *pdpy;
723 ARRAY8 authorizationName, authorizationData;
724 ARRAY8Ptr connectionAddress;
726 Debug ("Request respond %d\n", length);
727 connectionTypes.data = 0;
728 connectionAddresses.data = 0;
729 authenticationName.data = 0;
730 authenticationData.data = 0;
731 authorizationNames.data = 0;
732 authorizationName.length = 0;
733 authorizationData.length = 0;
734 manufacturerDisplayID.data = 0;
735 if (XdmcpReadCARD16 (&buffer, &displayNumber) &&
736 XdmcpReadARRAY16 (&buffer, &connectionTypes) &&
737 XdmcpReadARRAYofARRAY8 (&buffer, &connectionAddresses) &&
738 XdmcpReadARRAY8 (&buffer, &authenticationName) &&
739 XdmcpReadARRAY8 (&buffer, &authenticationData) &&
740 XdmcpReadARRAYofARRAY8 (&buffer, &authorizationNames) &&
741 XdmcpReadARRAY8 (&buffer, &manufacturerDisplayID))
744 expectlen += 2; /* displayNumber */
745 expectlen += 1 + 2*connectionTypes.length; /* connectionTypes */
746 expectlen += 1; /* connectionAddresses */
747 for (i = 0; i < (int)connectionAddresses.length; i++)
748 expectlen += 2 + connectionAddresses.data[i].length;
749 expectlen += 2 + authenticationName.length; /* authenticationName */
750 expectlen += 2 + authenticationData.length; /* authenticationData */
751 expectlen += 1; /* authoriationNames */
752 for (i = 0; i < (int)authorizationNames.length; i++)
753 expectlen += 2 + authorizationNames.data[i].length;
754 expectlen += 2 + manufacturerDisplayID.length; /* displayID */
755 if (expectlen != length)
757 Debug ("Request length error got %d expect %d\n", length, expectlen);
760 if (connectionTypes.length == 0 ||
761 connectionAddresses.length != connectionTypes.length)
763 reason = &noValidAddr;
767 pdpy = FindProtoDisplay (from, fromlen, displayNumber);
770 /* Check this Display against the Manager's policy */
771 reason = Accept (from, fromlen, displayNumber);
775 /* Check the Display's stream services against Manager's policy */
776 i = SelectConnectionTypeIndex (&connectionTypes,
777 &connectionAddresses);
779 reason = &noValidAddr;
783 /* The Manager considers this a new session */
784 connectionAddress = &connectionAddresses.data[i];
785 pdpy = NewProtoDisplay (from, fromlen, displayNumber,
786 connectionTypes.data[i], connectionAddress,
788 Debug ("NewProtoDisplay 0x%x\n", pdpy);
790 reason = &outOfMemory;
794 if (authorizationNames.length == 0)
797 j = SelectAuthorizationTypeIndex (&authenticationName,
798 &authorizationNames);
801 reason = &noValidAuth;
804 if (!CheckAuthentication (pdpy,
805 &manufacturerDisplayID,
807 &authenticationData))
809 reason = &noAuthentic;
812 if (j < (int)authorizationNames.length)
815 SetProtoDisplayAuthorization (pdpy,
816 (unsigned short) authorizationNames.data[j].length,
817 (char *) authorizationNames.data[j].data);
818 auth = pdpy->xdmcpAuthorization;
820 auth = pdpy->fileAuthorization;
823 authorizationName.length = auth->name_length;
824 authorizationName.data = (CARD8Ptr) auth->name;
825 authorizationData.length = auth->data_length;
826 authorizationData.data = (CARD8Ptr) auth->data;
831 send_accept (from, fromlen, pdpy->sessionID,
840 send_decline (from, fromlen, &authenticationName,
844 DisposeProtoDisplay (pdpy);
848 XdmcpDisposeARRAY16 (&connectionTypes);
849 XdmcpDisposeARRAYofARRAY8 (&connectionAddresses);
850 XdmcpDisposeARRAY8 (&authenticationName);
851 XdmcpDisposeARRAY8 (&authenticationData);
852 XdmcpDisposeARRAYofARRAY8 (&authorizationNames);
853 XdmcpDisposeARRAY8 (&manufacturerDisplayID);
856 send_accept (to, tolen, sessionID,
857 authenticationName, authenticationData,
858 authorizationName, authorizationData)
862 ARRAY8Ptr authenticationName, authenticationData;
863 ARRAY8Ptr authorizationName, authorizationData;
867 Debug ("Accept Session ID %d\n", sessionID);
868 header.version = XDM_PROTOCOL_VERSION;
869 header.opcode = (CARD16) ACCEPT;
870 header.length = 4; /* session ID */
871 header.length += 2 + authenticationName->length;
872 header.length += 2 + authenticationData->length;
873 header.length += 2 + authorizationName->length;
874 header.length += 2 + authorizationData->length;
875 XdmcpWriteHeader (&buffer, &header);
876 XdmcpWriteCARD32 (&buffer, sessionID);
877 XdmcpWriteARRAY8 (&buffer, authenticationName);
878 XdmcpWriteARRAY8 (&buffer, authenticationData);
879 XdmcpWriteARRAY8 (&buffer, authorizationName);
880 XdmcpWriteARRAY8 (&buffer, authorizationData);
881 XdmcpFlush (xdmcpFd, &buffer, to, tolen);
884 send_decline (to, tolen, authenticationName, authenticationData, status)
887 ARRAY8Ptr authenticationName, authenticationData;
892 Debug ("Decline %*.*s\n", status->length, status->length, pS(status->data));
893 header.version = XDM_PROTOCOL_VERSION;
894 header.opcode = (CARD16) DECLINE;
896 header.length += 2 + status->length;
897 header.length += 2 + authenticationName->length;
898 header.length += 2 + authenticationData->length;
899 XdmcpWriteHeader (&buffer, &header);
900 XdmcpWriteARRAY8 (&buffer, status);
901 XdmcpWriteARRAY8 (&buffer, authenticationName);
902 XdmcpWriteARRAY8 (&buffer, authenticationData);
903 XdmcpFlush (xdmcpFd, &buffer, to, tolen);
906 manage (from, fromlen, length)
907 struct sockaddr *from;
912 CARD16 displayNumber;
915 struct protoDisplay *pdpy;
919 XdmcpNetaddr from_save;
920 ARRAY8 clientAddress, clientPort;
921 CARD16 connectionType;
923 Debug ("Manage %d\n", length);
924 displayClass.data = 0;
925 displayClass.length = 0;
926 if (XdmcpReadCARD32 (&buffer, &sessionID) &&
927 XdmcpReadCARD16 (&buffer, &displayNumber) &&
928 XdmcpReadARRAY8 (&buffer, &displayClass))
930 expectlen = 4 + /* session ID */
931 2 + /* displayNumber */
932 2 + displayClass.length; /* displayClass */
933 if (expectlen != length)
935 Debug ("Manage length error got %d expect %d\n", length, expectlen);
938 pdpy = FindProtoDisplay (from, fromlen, displayNumber);
939 Debug ("Manage Session ID %d, pdpy 0x%x\n", sessionID, pdpy);
940 if (!pdpy || pdpy->sessionID != sessionID)
943 * We may have already started a session for this display
944 * but it hasn't seen the response in the form of an
945 * XOpenDisplay() yet. So check if it is in the list of active
946 * displays, and if so check that the session id's match.
947 * If all this is true, then we have a duplicate request that
951 && (d = FindDisplayByAddress(from, fromlen, displayNumber))
952 && d->sessionID == sessionID) {
953 Debug("manage: got duplicate pkt, ignoring\n");
956 Debug ("Session ID %d refused\n", sessionID);
958 Debug ("Existing Session ID %d\n", pdpy->sessionID);
959 send_refuse (from, fromlen, sessionID);
963 name = NetworkAddressToName (pdpy->connectionType,
964 &pdpy->connectionAddress,
965 pdpy->displayNumber);
966 Debug ("Computed display name: %s\n", name);
969 send_failed (from, fromlen, "(no name)", sessionID, "out of memory");
972 d = FindDisplayByName (name);
975 extern void StopDisplay ();
977 Debug ("Terminating active session for %s\n", d->name);
980 class = malloc (displayClass.length + 1);
983 send_failed (from, fromlen, name, sessionID, "out of memory");
986 if (displayClass.length)
988 memmove( class, displayClass.data, displayClass.length);
989 class[displayClass.length] = '\0';
993 free ((char *) class);
994 class = (char *) NULL;
996 from_save = (XdmcpNetaddr) malloc (fromlen);
999 send_failed (from, fromlen, name, sessionID, "out of memory");
1002 memmove( from_save, from, fromlen);
1003 d = NewDisplay (name, class);
1006 free ((char *) from_save);
1007 send_failed (from, fromlen, name, sessionID, "out of memory");
1010 d->displayType.location = Foreign;
1011 d->displayType.lifetime = Transient;
1012 d->displayType.origin = FromXDMCP;
1013 d->sessionID = pdpy->sessionID;
1014 d->from = (struct sockaddr *)from_save;
1015 d->fromlen = fromlen;
1016 d->displayNumber = pdpy->displayNumber;
1019 #endif /* BYPASSLOGIN */
1020 ClientAddress (from, &clientAddress, &clientPort, &connectionType);
1022 if (IsIndirectClient (&clientAddress, connectionType))
1024 Debug ("IsIndirectClient\n");
1025 ForgetIndirectClient (&clientAddress, connectionType);
1026 if (UseChooser (&clientAddress, connectionType))
1029 Debug ("Use chooser for %s\n", d->name);
1032 d->clientAddr = clientAddress;
1033 d->connectionType = connectionType;
1034 XdmcpDisposeARRAY8 (&clientPort);
1035 if (pdpy->fileAuthorization)
1037 d->authorizations = (Xauth **) malloc (sizeof (Xauth *));
1038 if (!d->authorizations)
1040 free ((char *) from_save);
1042 send_failed (from, fromlen, name, sessionID, "out of memory");
1045 d->authorizations[0] = pdpy->fileAuthorization;
1047 pdpy->fileAuthorization = 0;
1049 DisposeProtoDisplay (pdpy);
1050 Debug ("Starting display %s,%s\n", d->name, d->class);
1055 XdmcpDisposeARRAY8 (&displayClass);
1056 if (name) free ((char*) name);
1057 if (class) free ((char*) class);
1060 void SendFailed (d, reason)
1064 Debug ("Display start failed, sending Failed\n");
1065 send_failed (d->from, d->fromlen, d->name, d->sessionID, reason);
1068 send_failed (from, fromlen, name, sessionID, reason)
1069 struct sockaddr *from;
1075 static char buf[256];
1079 sprintf (buf, "Session %d failed for display %s: %s",
1080 sessionID, name, reason);
1081 Debug ("Send failed %d %s\n", sessionID, buf);
1082 status.length = strlen (buf);
1083 status.data = (CARD8Ptr) buf;
1084 header.version = XDM_PROTOCOL_VERSION;
1085 header.opcode = (CARD16) FAILED;
1086 header.length = 6 + status.length;
1087 XdmcpWriteHeader (&buffer, &header);
1088 XdmcpWriteCARD32 (&buffer, sessionID);
1089 XdmcpWriteARRAY8 (&buffer, &status);
1090 XdmcpFlush (xdmcpFd, &buffer, from, fromlen);
1093 send_refuse (from, fromlen, sessionID)
1094 struct sockaddr *from;
1100 Debug ("Send refuse %d\n", sessionID);
1101 header.version = XDM_PROTOCOL_VERSION;
1102 header.opcode = (CARD16) REFUSE;
1104 XdmcpWriteHeader (&buffer, &header);
1105 XdmcpWriteCARD32 (&buffer, sessionID);
1106 XdmcpFlush (xdmcpFd, &buffer, from, fromlen);
1109 send_alive (from, fromlen, length)
1110 struct sockaddr *from;
1115 CARD16 displayNumber;
1119 CARD32 sendSessionID;
1121 Debug ("Send alive\n");
1122 if (XdmcpReadCARD16 (&buffer, &displayNumber) &&
1123 XdmcpReadCARD32 (&buffer, &sessionID))
1127 d = FindDisplayBySessionID (sessionID);
1129 d = FindDisplayByAddress (from, fromlen, displayNumber);
1133 if (d && d->status == running)
1135 if (d->sessionID == sessionID)
1137 sendSessionID = d->sessionID;
1139 header.version = XDM_PROTOCOL_VERSION;
1140 header.opcode = (CARD16) ALIVE;
1142 Debug ("alive: %d %d\n", sendRunning, sendSessionID);
1143 XdmcpWriteHeader (&buffer, &header);
1144 XdmcpWriteCARD8 (&buffer, sendRunning);
1145 XdmcpWriteCARD32 (&buffer, sendSessionID);
1146 XdmcpFlush (xdmcpFd, &buffer, from, fromlen);
1152 NetworkAddressToHostname (connectionType, connectionAddress)
1153 #if NeedWidePrototypes
1156 CARD16 connectionType;
1158 ARRAY8Ptr connectionAddress;
1162 switch (connectionType)
1164 case FamilyInternet:
1166 struct hostent *hostent;
1170 hostent = gethostbyaddr ((char *)connectionAddress->data,
1171 connectionAddress->length, AF_INET);
1174 local_name = hostent->h_name;
1176 /* can't get name, so use emergency fallback */
1177 sprintf(dotted, "%d.%d.%d.%d",
1178 connectionAddress->data[0],
1179 connectionAddress->data[1],
1180 connectionAddress->data[2],
1181 connectionAddress->data[3]);
1182 local_name = dotted;
1184 LogError ((unsigned char *)"Cannot convert Internet address %s to host name\n",
1187 if (!getString (name, strlen (local_name)))
1189 strcpy (name, local_name);
1203 HostnameToNetworkAddress (name, connectionType, connectionAddress)
1205 CARD16 connectionType;
1206 ARRAY8Ptr connectionAddress;
1208 switch (connectionType)
1210 case FamilyInternet:
1212 struct hostent *hostent;
1214 hostent = gethostbyname (name);
1217 if (!XdmcpAllocARRAY8 (connectionAddress, hostent->h_length))
1219 memmove( connectionAddress->data, hostent->h_addr, hostent->h_length);
1231 * converts a display name into a network address, using
1232 * the same rules as XOpenDisplay (algorithm cribbed from there)
1236 NameToNetworkAddress(name, connectionTypep, connectionAddress, displayNumber)
1238 CARD16Ptr connectionTypep;
1239 ARRAY8Ptr connectionAddress;
1240 CARD16Ptr displayNumber;
1242 char *colon, *display_number;
1243 char hostname[1024];
1246 CARD16 connectionType;
1248 colon = strchr(name, ':');
1253 if (colon - name > sizeof (hostname))
1255 strncpy (hostname, name, colon - name);
1256 hostname[colon - name] = '\0';
1260 strcpy (hostname, localHostname ());
1262 if (colon[1] == ':')
1271 display_number = colon + 1;
1272 while (*display_number && *display_number != '.')
1274 if (!isascii (*display_number) || !isdigit(*display_number))
1277 if (display_number == colon + 1)
1279 number = atoi (colon + 1);
1282 connectionType = FamilyDECnet;
1285 connectionType = FamilyInternet;
1286 if (!HostnameToNetworkAddress (hostname, connectionType, connectionAddress))
1288 *displayNumber = number;
1289 *connectionTypep = connectionType;