xdmcp.c revision 35c4bbdf
1/* 2 * Copyright 1989 Network Computing Devices, Inc., Mountain View, California. 3 * 4 * Permission to use, copy, modify, and distribute this software and its 5 * documentation for any purpose and without fee is hereby granted, provided 6 * that the above copyright notice appear in all copies and that both that 7 * copyright notice and this permission notice appear in supporting 8 * documentation, and that the name of N.C.D. not be used in advertising or 9 * publicity pertaining to distribution of the software without specific, 10 * written prior permission. N.C.D. makes no representations about the 11 * suitability of this software for any purpose. It is provided "as is" 12 * without express or implied warranty. 13 * 14 */ 15 16#ifdef HAVE_DIX_CONFIG_H 17#include <dix-config.h> 18#endif 19 20#ifdef WIN32 21#include <X11/Xwinsock.h> 22#define XSERV_t 23#define TRANS_SERVER 24#define TRANS_REOPEN 25#include <X11/Xtrans/Xtrans.h> 26#endif 27 28#include <X11/Xos.h> 29 30#if !defined(WIN32) 31#include <sys/param.h> 32#include <sys/socket.h> 33#include <netinet/in.h> 34#include <netdb.h> 35#endif 36 37#include <stdio.h> 38#include <stdlib.h> 39#include <X11/X.h> 40#include <X11/Xmd.h> 41#include "misc.h" 42#include <X11/Xpoll.h> 43#include "osdep.h" 44#include "input.h" 45#include "dixstruct.h" 46#include "opaque.h" 47#include "site.h" 48 49#ifdef STREAMSCONN 50#include <tiuser.h> 51#include <netconfig.h> 52#include <netdir.h> 53#endif 54 55#define XSERV_t 56#define TRANS_SERVER 57#define TRANS_REOPEN 58#include <X11/Xtrans/Xtrans.h> 59 60#ifdef XDMCP 61#undef REQUEST 62 63#ifdef XDMCP_NO_IPV6 64#undef IPv6 65#endif 66 67#include <X11/Xdmcp.h> 68 69#define X_INCLUDE_NETDB_H 70#include <X11/Xos_r.h> 71 72static const char *defaultDisplayClass = COMPILEDDISPLAYCLASS; 73 74static int xdmcpSocket, sessionSocket; 75static xdmcp_states state; 76 77#if defined(IPv6) && defined(AF_INET6) 78static int xdmcpSocket6; 79static struct sockaddr_storage req_sockaddr; 80#else 81static struct sockaddr_in req_sockaddr; 82#endif 83static int req_socklen; 84static CARD32 SessionID; 85static CARD32 timeOutTime; 86static int timeOutRtx; 87static CARD16 DisplayNumber; 88static xdmcp_states XDM_INIT_STATE = XDM_OFF; 89 90#ifdef HASXDMAUTH 91static char *xdmAuthCookie; 92#endif 93 94static XdmcpBuffer buffer; 95 96#if defined(IPv6) && defined(AF_INET6) 97 98static struct addrinfo *mgrAddr; 99static struct addrinfo *mgrAddrFirst; 100 101#define SOCKADDR_TYPE struct sockaddr_storage 102#define SOCKADDR_FAMILY(s) ((struct sockaddr *)&(s))->sa_family 103 104#ifdef BSD44SOCKETS 105#define SOCKLEN_FIELD(s) ((struct sockaddr *)&(s))->sa_len 106#define SOCKLEN_TYPE unsigned char 107#else 108#define SOCKLEN_TYPE unsigned int 109#endif 110 111#else 112 113#define SOCKADDR_TYPE struct sockaddr_in 114#define SOCKADDR_FAMILY(s) (s).sin_family 115 116#ifdef BSD44SOCKETS 117#define SOCKLEN_FIELD(s) (s).sin_len 118#define SOCKLEN_TYPE unsigned char 119#else 120#define SOCKLEN_TYPE size_t 121#endif 122 123#endif 124 125static SOCKADDR_TYPE ManagerAddress; 126static SOCKADDR_TYPE FromAddress; 127 128#ifdef SOCKLEN_FIELD 129#define ManagerAddressLen SOCKLEN_FIELD(ManagerAddress) 130#define FromAddressLen SOCKLEN_FIELD(FromAddress) 131#else 132static SOCKLEN_TYPE ManagerAddressLen, FromAddressLen; 133#endif 134 135#if defined(IPv6) && defined(AF_INET6) 136static struct multicastinfo { 137 struct multicastinfo *next; 138 struct addrinfo *ai; 139 int hops; 140} *mcastlist; 141#endif 142 143static void XdmcpAddHost(const struct sockaddr *from, 144 int fromlen, 145 ARRAY8Ptr AuthenticationName, 146 ARRAY8Ptr hostname, ARRAY8Ptr status); 147 148static void XdmcpSelectHost(const struct sockaddr *host_sockaddr, 149 int host_len, ARRAY8Ptr AuthenticationName); 150 151static void get_xdmcp_sock(void); 152 153static void send_query_msg(void); 154 155static void recv_willing_msg(struct sockaddr *from, 156 int fromlen, 157 unsigned length); 158 159static void send_request_msg(void); 160 161static void recv_accept_msg(unsigned length); 162 163static void recv_decline_msg(unsigned length); 164 165static void send_manage_msg(void); 166 167static void recv_refuse_msg(unsigned length); 168 169static void recv_failed_msg(unsigned length); 170 171static void send_keepalive_msg(void); 172 173static void recv_alive_msg(unsigned length ); 174 175static void XdmcpFatal(const char *type, 176 ARRAY8Ptr status); 177 178static void XdmcpWarning(const char *str); 179 180static void get_manager_by_name(int argc, 181 char **argv, 182 int i); 183 184static void get_fromaddr_by_name(int argc, 185 char **argv, 186 int i); 187 188#if defined(IPv6) && defined(AF_INET6) 189static int get_mcast_options(int argc, 190 char **argv, 191 int i); 192#endif 193 194static void receive_packet(int socketfd); 195 196static void send_packet(void); 197 198static void timeout(void); 199 200static void XdmcpBlockHandler(void *data , 201 struct timeval **wt, 202 void *LastSelectMask); 203 204static void XdmcpWakeupHandler(void *data, 205 int i, 206 void *LastSelectMask); 207 208/* 209 * Register the Manufacturer display ID 210 */ 211 212static ARRAY8 ManufacturerDisplayID; 213 214static void 215XdmcpRegisterManufacturerDisplayID(const char *name, int length) 216{ 217 int i; 218 219 XdmcpDisposeARRAY8(&ManufacturerDisplayID); 220 if (!XdmcpAllocARRAY8(&ManufacturerDisplayID, length)) 221 return; 222 for (i = 0; i < length; i++) 223 ManufacturerDisplayID.data[i] = (CARD8) name[i]; 224} 225 226static unsigned short xdm_udp_port = XDM_UDP_PORT; 227static Bool OneSession = FALSE; 228static const char *xdm_from = NULL; 229 230void 231XdmcpUseMsg(void) 232{ 233 ErrorF("-query host-name contact named host for XDMCP\n"); 234 ErrorF("-broadcast broadcast for XDMCP\n"); 235#if defined(IPv6) && defined(AF_INET6) 236 ErrorF("-multicast [addr [hops]] IPv6 multicast for XDMCP\n"); 237#endif 238 ErrorF("-indirect host-name contact named host for indirect XDMCP\n"); 239 ErrorF("-port port-num UDP port number to send messages to\n"); 240 ErrorF 241 ("-from local-address specify the local address to connect from\n"); 242 ErrorF("-once Terminate server after one session\n"); 243 ErrorF("-class display-class specify display class to send in manage\n"); 244#ifdef HASXDMAUTH 245 ErrorF("-cookie xdm-auth-bits specify the magic cookie for XDMCP\n"); 246#endif 247 ErrorF("-displayID display-id manufacturer display ID for request\n"); 248} 249 250static void 251XdmcpDefaultListen(void) 252{ 253 /* Even when configured --disable-listen-tcp, we should listen on tcp in 254 XDMCP modes */ 255 _XSERVTransListen("tcp"); 256} 257 258int 259XdmcpOptions(int argc, char **argv, int i) 260{ 261 if (strcmp(argv[i], "-query") == 0) { 262 get_manager_by_name(argc, argv, i++); 263 XDM_INIT_STATE = XDM_QUERY; 264 AccessUsingXdmcp(); 265 XdmcpDefaultListen(); 266 return i + 1; 267 } 268 if (strcmp(argv[i], "-broadcast") == 0) { 269 XDM_INIT_STATE = XDM_BROADCAST; 270 AccessUsingXdmcp(); 271 XdmcpDefaultListen(); 272 return i + 1; 273 } 274#if defined(IPv6) && defined(AF_INET6) 275 if (strcmp(argv[i], "-multicast") == 0) { 276 i = get_mcast_options(argc, argv, ++i); 277 XDM_INIT_STATE = XDM_MULTICAST; 278 AccessUsingXdmcp(); 279 XdmcpDefaultListen(); 280 return i + 1; 281 } 282#endif 283 if (strcmp(argv[i], "-indirect") == 0) { 284 get_manager_by_name(argc, argv, i++); 285 XDM_INIT_STATE = XDM_INDIRECT; 286 AccessUsingXdmcp(); 287 XdmcpDefaultListen(); 288 return i + 1; 289 } 290 if (strcmp(argv[i], "-port") == 0) { 291 if (++i == argc) { 292 FatalError("Xserver: missing port number in command line\n"); 293 } 294 xdm_udp_port = (unsigned short) atoi(argv[i]); 295 return i + 1; 296 } 297 if (strcmp(argv[i], "-from") == 0) { 298 get_fromaddr_by_name(argc, argv, ++i); 299 return i + 1; 300 } 301 if (strcmp(argv[i], "-once") == 0) { 302 OneSession = TRUE; 303 return i + 1; 304 } 305 if (strcmp(argv[i], "-class") == 0) { 306 if (++i == argc) { 307 FatalError("Xserver: missing class name in command line\n"); 308 } 309 defaultDisplayClass = argv[i]; 310 return i + 1; 311 } 312#ifdef HASXDMAUTH 313 if (strcmp(argv[i], "-cookie") == 0) { 314 if (++i == argc) { 315 FatalError("Xserver: missing cookie data in command line\n"); 316 } 317 xdmAuthCookie = argv[i]; 318 return i + 1; 319 } 320#endif 321 if (strcmp(argv[i], "-displayID") == 0) { 322 if (++i == argc) { 323 FatalError("Xserver: missing displayID in command line\n"); 324 } 325 XdmcpRegisterManufacturerDisplayID(argv[i], strlen(argv[i])); 326 return i + 1; 327 } 328 return i; 329} 330 331/* 332 * This section is a collection of routines for 333 * registering server-specific data with the XDMCP 334 * state machine. 335 */ 336 337/* 338 * Save all broadcast addresses away so BroadcastQuery 339 * packets get sent everywhere 340 */ 341 342#define MAX_BROADCAST 10 343 344/* This stays sockaddr_in since IPv6 doesn't support broadcast */ 345static struct sockaddr_in BroadcastAddresses[MAX_BROADCAST]; 346static int NumBroadcastAddresses; 347 348void 349XdmcpRegisterBroadcastAddress(const struct sockaddr_in *addr) 350{ 351 struct sockaddr_in *bcast; 352 353 if (NumBroadcastAddresses >= MAX_BROADCAST) 354 return; 355 bcast = &BroadcastAddresses[NumBroadcastAddresses++]; 356 memset(bcast, 0, sizeof(struct sockaddr_in)); 357#ifdef BSD44SOCKETS 358 bcast->sin_len = addr->sin_len; 359#endif 360 bcast->sin_family = addr->sin_family; 361 bcast->sin_port = htons(xdm_udp_port); 362 bcast->sin_addr = addr->sin_addr; 363} 364 365/* 366 * Each authentication type is registered here; Validator 367 * will be called to check all access attempts using 368 * the specified authentication type 369 */ 370 371static ARRAYofARRAY8 AuthenticationNames, AuthenticationDatas; 372typedef struct _AuthenticationFuncs { 373 ValidatorFunc Validator; 374 GeneratorFunc Generator; 375 AddAuthorFunc AddAuth; 376} AuthenticationFuncsRec, *AuthenticationFuncsPtr; 377 378static AuthenticationFuncsPtr AuthenticationFuncsList; 379 380void 381XdmcpRegisterAuthentication(const char *name, 382 int namelen, 383 const char *data, 384 int datalen, 385 ValidatorFunc Validator, 386 GeneratorFunc Generator, AddAuthorFunc AddAuth) 387{ 388 int i; 389 ARRAY8 AuthenticationName, AuthenticationData; 390 static AuthenticationFuncsPtr newFuncs; 391 392 if (!XdmcpAllocARRAY8(&AuthenticationName, namelen)) 393 return; 394 if (!XdmcpAllocARRAY8(&AuthenticationData, datalen)) { 395 XdmcpDisposeARRAY8(&AuthenticationName); 396 return; 397 } 398 for (i = 0; i < namelen; i++) 399 AuthenticationName.data[i] = name[i]; 400 for (i = 0; i < datalen; i++) 401 AuthenticationData.data[i] = data[i]; 402 if (!(XdmcpReallocARRAYofARRAY8(&AuthenticationNames, 403 AuthenticationNames.length + 1) && 404 XdmcpReallocARRAYofARRAY8(&AuthenticationDatas, 405 AuthenticationDatas.length + 1) && 406 (newFuncs = 407 malloc((AuthenticationNames.length + 408 1) * sizeof(AuthenticationFuncsRec))))) { 409 XdmcpDisposeARRAY8(&AuthenticationName); 410 XdmcpDisposeARRAY8(&AuthenticationData); 411 return; 412 } 413 for (i = 0; i < AuthenticationNames.length - 1; i++) 414 newFuncs[i] = AuthenticationFuncsList[i]; 415 newFuncs[AuthenticationNames.length - 1].Validator = Validator; 416 newFuncs[AuthenticationNames.length - 1].Generator = Generator; 417 newFuncs[AuthenticationNames.length - 1].AddAuth = AddAuth; 418 free(AuthenticationFuncsList); 419 AuthenticationFuncsList = newFuncs; 420 AuthenticationNames.data[AuthenticationNames.length - 1] = 421 AuthenticationName; 422 AuthenticationDatas.data[AuthenticationDatas.length - 1] = 423 AuthenticationData; 424} 425 426/* 427 * Select the authentication type to be used; this is 428 * set by the manager of the host to be connected to. 429 */ 430 431static ARRAY8 noAuthenticationName = { (CARD16) 0, (CARD8Ptr) 0 }; 432static ARRAY8 noAuthenticationData = { (CARD16) 0, (CARD8Ptr) 0 }; 433 434static ARRAY8Ptr AuthenticationName = &noAuthenticationName; 435static ARRAY8Ptr AuthenticationData = &noAuthenticationData; 436static AuthenticationFuncsPtr AuthenticationFuncs; 437 438static void 439XdmcpSetAuthentication(const ARRAY8Ptr name) 440{ 441 int i; 442 443 for (i = 0; i < AuthenticationNames.length; i++) 444 if (XdmcpARRAY8Equal(&AuthenticationNames.data[i], name)) { 445 AuthenticationName = &AuthenticationNames.data[i]; 446 AuthenticationData = &AuthenticationDatas.data[i]; 447 AuthenticationFuncs = &AuthenticationFuncsList[i]; 448 break; 449 } 450} 451 452/* 453 * Register the host address for the display 454 */ 455 456static ARRAY16 ConnectionTypes; 457static ARRAYofARRAY8 ConnectionAddresses; 458static long xdmcpGeneration; 459 460void 461XdmcpRegisterConnection(int type, const char *address, int addrlen) 462{ 463 int i; 464 CARD8 *newAddress; 465 466 if (xdmcpGeneration != serverGeneration) { 467 XdmcpDisposeARRAY16(&ConnectionTypes); 468 XdmcpDisposeARRAYofARRAY8(&ConnectionAddresses); 469 xdmcpGeneration = serverGeneration; 470 } 471 if (xdm_from != NULL) { /* Only register the requested address */ 472 const void *regAddr = address; 473 const void *fromAddr = NULL; 474 int regAddrlen = addrlen; 475 476 if (addrlen == sizeof(struct in_addr)) { 477 if (SOCKADDR_FAMILY(FromAddress) == AF_INET) { 478 fromAddr = &((struct sockaddr_in *) &FromAddress)->sin_addr; 479 } 480#if defined(IPv6) && defined(AF_INET6) 481 else if ((SOCKADDR_FAMILY(FromAddress) == AF_INET6) && 482 IN6_IS_ADDR_V4MAPPED(& 483 ((struct sockaddr_in6 *) 484 &FromAddress)->sin6_addr)) { 485 fromAddr = 486 &((struct sockaddr_in6 *) &FromAddress)->sin6_addr. 487 s6_addr[12]; 488 } 489#endif 490 } 491#if defined(IPv6) && defined(AF_INET6) 492 else if (addrlen == sizeof(struct in6_addr)) { 493 if (SOCKADDR_FAMILY(FromAddress) == AF_INET6) { 494 fromAddr = &((struct sockaddr_in6 *) &FromAddress)->sin6_addr; 495 } 496 else if ((SOCKADDR_FAMILY(FromAddress) == AF_INET) && 497 IN6_IS_ADDR_V4MAPPED((const struct in6_addr *) address)) { 498 fromAddr = &((struct sockaddr_in *) &FromAddress)->sin_addr; 499 regAddr = 500 &((struct sockaddr_in6 *) &address)->sin6_addr.s6_addr[12]; 501 regAddrlen = sizeof(struct in_addr); 502 } 503 } 504#endif 505 if (!fromAddr || memcmp(regAddr, fromAddr, regAddrlen) != 0) { 506 return; 507 } 508 } 509 if (ConnectionAddresses.length + 1 == 256) 510 return; 511 newAddress = malloc(addrlen * sizeof(CARD8)); 512 if (!newAddress) 513 return; 514 if (!XdmcpReallocARRAY16(&ConnectionTypes, ConnectionTypes.length + 1)) { 515 free(newAddress); 516 return; 517 } 518 if (!XdmcpReallocARRAYofARRAY8(&ConnectionAddresses, 519 ConnectionAddresses.length + 1)) { 520 free(newAddress); 521 return; 522 } 523 ConnectionTypes.data[ConnectionTypes.length - 1] = (CARD16) type; 524 for (i = 0; i < addrlen; i++) 525 newAddress[i] = address[i]; 526 ConnectionAddresses.data[ConnectionAddresses.length - 1].data = newAddress; 527 ConnectionAddresses.data[ConnectionAddresses.length - 1].length = addrlen; 528} 529 530/* 531 * Register an Authorization Name. XDMCP advertises this list 532 * to the manager. 533 */ 534 535static ARRAYofARRAY8 AuthorizationNames; 536 537void 538XdmcpRegisterAuthorizations(void) 539{ 540 XdmcpDisposeARRAYofARRAY8(&AuthorizationNames); 541 RegisterAuthorizations(); 542} 543 544void 545XdmcpRegisterAuthorization(const char *name, int namelen) 546{ 547 ARRAY8 authName; 548 int i; 549 550 authName.data = malloc(namelen * sizeof(CARD8)); 551 if (!authName.data) 552 return; 553 if (!XdmcpReallocARRAYofARRAY8 554 (&AuthorizationNames, AuthorizationNames.length + 1)) { 555 free(authName.data); 556 return; 557 } 558 for (i = 0; i < namelen; i++) 559 authName.data[i] = (CARD8) name[i]; 560 authName.length = namelen; 561 AuthorizationNames.data[AuthorizationNames.length - 1] = authName; 562} 563 564/* 565 * Register the DisplayClass string 566 */ 567 568static ARRAY8 DisplayClass; 569 570static void 571XdmcpRegisterDisplayClass(const char *name, int length) 572{ 573 int i; 574 575 XdmcpDisposeARRAY8(&DisplayClass); 576 if (!XdmcpAllocARRAY8(&DisplayClass, length)) 577 return; 578 for (i = 0; i < length; i++) 579 DisplayClass.data[i] = (CARD8) name[i]; 580} 581 582/* 583 * initialize XDMCP; create the socket, compute the display 584 * number, set up the state machine 585 */ 586 587void 588XdmcpInit(void) 589{ 590 state = XDM_INIT_STATE; 591#ifdef HASXDMAUTH 592 if (xdmAuthCookie) 593 XdmAuthenticationInit(xdmAuthCookie, strlen(xdmAuthCookie)); 594#endif 595 if (state != XDM_OFF) { 596 XdmcpRegisterAuthorizations(); 597 XdmcpRegisterDisplayClass(defaultDisplayClass, 598 strlen(defaultDisplayClass)); 599 AccessUsingXdmcp(); 600 RegisterBlockAndWakeupHandlers(XdmcpBlockHandler, XdmcpWakeupHandler, 601 (void *) 0); 602 timeOutRtx = 0; 603 DisplayNumber = (CARD16) atoi(display); 604 get_xdmcp_sock(); 605 send_packet(); 606 } 607} 608 609void 610XdmcpReset(void) 611{ 612 state = XDM_INIT_STATE; 613 if (state != XDM_OFF) { 614 RegisterBlockAndWakeupHandlers(XdmcpBlockHandler, XdmcpWakeupHandler, 615 (void *) 0); 616 timeOutRtx = 0; 617 send_packet(); 618 } 619} 620 621/* 622 * Called whenever a new connection is created; notices the 623 * first connection and saves it to terminate the session 624 * when it is closed 625 */ 626 627void 628XdmcpOpenDisplay(int sock) 629{ 630 if (state != XDM_AWAIT_MANAGE_RESPONSE) 631 return; 632 state = XDM_RUN_SESSION; 633 timeOutTime = GetTimeInMillis() + XDM_DEF_DORMANCY * 1000; 634 sessionSocket = sock; 635} 636 637void 638XdmcpCloseDisplay(int sock) 639{ 640 if ((state != XDM_RUN_SESSION && state != XDM_AWAIT_ALIVE_RESPONSE) 641 || sessionSocket != sock) 642 return; 643 state = XDM_INIT_STATE; 644 if (OneSession) 645 dispatchException |= DE_TERMINATE; 646 else 647 dispatchException |= DE_RESET; 648 isItTimeToYield = TRUE; 649} 650 651/* 652 * called before going to sleep, this routine 653 * may modify the timeout value about to be sent 654 * to select; in this way XDMCP can do appropriate things 655 * dynamically while starting up 656 */ 657 658 /*ARGSUSED*/ static void 659XdmcpBlockHandler(void *data, /* unused */ 660 struct timeval **wt, void *pReadmask) 661{ 662 fd_set *last_select_mask = (fd_set *) pReadmask; 663 CARD32 millisToGo; 664 665 if (state == XDM_OFF) 666 return; 667 FD_SET(xdmcpSocket, last_select_mask); 668#if defined(IPv6) && defined(AF_INET6) 669 if (xdmcpSocket6 >= 0) 670 FD_SET(xdmcpSocket6, last_select_mask); 671#endif 672 if (timeOutTime == 0) 673 return; 674 millisToGo = timeOutTime - GetTimeInMillis(); 675 if ((int) millisToGo < 0) 676 millisToGo = 0; 677 AdjustWaitForDelay(wt, millisToGo); 678} 679 680/* 681 * called after select returns; this routine will 682 * recognise when XDMCP packets await and 683 * process them appropriately 684 */ 685 686 /*ARGSUSED*/ static void 687XdmcpWakeupHandler(void *data, /* unused */ 688 int i, void *pReadmask) 689{ 690 fd_set *last_select_mask = (fd_set *) pReadmask; 691 692 if (state == XDM_OFF) 693 return; 694 if (i > 0) { 695 if (FD_ISSET(xdmcpSocket, last_select_mask)) { 696 receive_packet(xdmcpSocket); 697 FD_CLR(xdmcpSocket, last_select_mask); 698 } 699#if defined(IPv6) && defined(AF_INET6) 700 if (xdmcpSocket6 >= 0 && FD_ISSET(xdmcpSocket6, last_select_mask)) { 701 receive_packet(xdmcpSocket6); 702 FD_CLR(xdmcpSocket6, last_select_mask); 703 } 704#endif 705 } 706 else if (timeOutTime && (int) (GetTimeInMillis() - timeOutTime) >= 0) { 707 if (state == XDM_RUN_SESSION) { 708 state = XDM_KEEPALIVE; 709 send_packet(); 710 } 711 else 712 timeout(); 713 } 714} 715 716/* 717 * This routine should be called from the routine that drives the 718 * user's host menu when the user selects a host 719 */ 720 721static void 722XdmcpSelectHost(const struct sockaddr *host_sockaddr, 723 int host_len, ARRAY8Ptr auth_name) 724{ 725 state = XDM_START_CONNECTION; 726 memmove(&req_sockaddr, host_sockaddr, host_len); 727 req_socklen = host_len; 728 XdmcpSetAuthentication(auth_name); 729 send_packet(); 730} 731 732/* 733 * !!! this routine should be replaced by a routine that adds 734 * the host to the user's host menu. the current version just 735 * selects the first host to respond with willing message. 736 */ 737 738 /*ARGSUSED*/ static void 739XdmcpAddHost(const struct sockaddr *from, 740 int fromlen, 741 ARRAY8Ptr auth_name, ARRAY8Ptr hostname, ARRAY8Ptr status) 742{ 743 XdmcpSelectHost(from, fromlen, auth_name); 744} 745 746/* 747 * A message is queued on the socket; read it and 748 * do the appropriate thing 749 */ 750 751static ARRAY8 UnwillingMessage = { (CARD8) 14, (CARD8 *) "Host unwilling" }; 752 753static void 754receive_packet(int socketfd) 755{ 756#if defined(IPv6) && defined(AF_INET6) 757 struct sockaddr_storage from; 758#else 759 struct sockaddr_in from; 760#endif 761 int fromlen = sizeof(from); 762 XdmcpHeader header; 763 764 /* read message off socket */ 765 if (!XdmcpFill(socketfd, &buffer, (XdmcpNetaddr) &from, &fromlen)) 766 return; 767 768 /* reset retransmission backoff */ 769 timeOutRtx = 0; 770 771 if (!XdmcpReadHeader(&buffer, &header)) 772 return; 773 774 if (header.version != XDM_PROTOCOL_VERSION) 775 return; 776 777 switch (header.opcode) { 778 case WILLING: 779 recv_willing_msg((struct sockaddr *) &from, fromlen, header.length); 780 break; 781 case UNWILLING: 782 XdmcpFatal("Manager unwilling", &UnwillingMessage); 783 break; 784 case ACCEPT: 785 recv_accept_msg(header.length); 786 break; 787 case DECLINE: 788 recv_decline_msg(header.length); 789 break; 790 case REFUSE: 791 recv_refuse_msg(header.length); 792 break; 793 case FAILED: 794 recv_failed_msg(header.length); 795 break; 796 case ALIVE: 797 recv_alive_msg(header.length); 798 break; 799 } 800} 801 802/* 803 * send the appropriate message given the current state 804 */ 805 806static void 807send_packet(void) 808{ 809 int rtx; 810 811 switch (state) { 812 case XDM_QUERY: 813 case XDM_BROADCAST: 814 case XDM_INDIRECT: 815#if defined(IPv6) && defined(AF_INET6) 816 case XDM_MULTICAST: 817#endif 818 send_query_msg(); 819 break; 820 case XDM_START_CONNECTION: 821 send_request_msg(); 822 break; 823 case XDM_MANAGE: 824 send_manage_msg(); 825 break; 826 case XDM_KEEPALIVE: 827 send_keepalive_msg(); 828 break; 829 default: 830 break; 831 } 832 rtx = (XDM_MIN_RTX << timeOutRtx); 833 if (rtx > XDM_MAX_RTX) 834 rtx = XDM_MAX_RTX; 835 timeOutTime = GetTimeInMillis() + rtx * 1000; 836} 837 838/* 839 * The session is declared dead for some reason; too many 840 * timeouts, or Keepalive failure. 841 */ 842 843static void 844XdmcpDeadSession(const char *reason) 845{ 846 ErrorF("XDM: %s, declaring session dead\n", reason); 847 state = XDM_INIT_STATE; 848 isItTimeToYield = TRUE; 849 dispatchException |= DE_RESET; 850 timeOutTime = 0; 851 timeOutRtx = 0; 852 send_packet(); 853} 854 855/* 856 * Timeout waiting for an XDMCP response. 857 */ 858 859static void 860timeout(void) 861{ 862 timeOutRtx++; 863 if (state == XDM_AWAIT_ALIVE_RESPONSE && timeOutRtx >= XDM_KA_RTX_LIMIT) { 864 XdmcpDeadSession("too many keepalive retransmissions"); 865 return; 866 } 867 else if (timeOutRtx >= XDM_RTX_LIMIT) { 868 /* Quit if "-once" specified, otherwise reset and try again. */ 869 if (OneSession) { 870 dispatchException |= DE_TERMINATE; 871 ErrorF("XDM: too many retransmissions\n"); 872 } 873 else { 874 XdmcpDeadSession("too many retransmissions"); 875 } 876 return; 877 } 878 879#if defined(IPv6) && defined(AF_INET6) 880 if (state == XDM_COLLECT_QUERY || state == XDM_COLLECT_INDIRECT_QUERY) { 881 /* Try next address */ 882 for (mgrAddr = mgrAddr->ai_next;; mgrAddr = mgrAddr->ai_next) { 883 if (mgrAddr == NULL) { 884 mgrAddr = mgrAddrFirst; 885 } 886 if (mgrAddr->ai_family == AF_INET || mgrAddr->ai_family == AF_INET6) 887 break; 888 } 889#ifndef SIN6_LEN 890 ManagerAddressLen = mgrAddr->ai_addrlen; 891#endif 892 memcpy(&ManagerAddress, mgrAddr->ai_addr, mgrAddr->ai_addrlen); 893 } 894#endif 895 896 switch (state) { 897 case XDM_COLLECT_QUERY: 898 state = XDM_QUERY; 899 break; 900 case XDM_COLLECT_BROADCAST_QUERY: 901 state = XDM_BROADCAST; 902 break; 903#if defined(IPv6) && defined(AF_INET6) 904 case XDM_COLLECT_MULTICAST_QUERY: 905 state = XDM_MULTICAST; 906 break; 907#endif 908 case XDM_COLLECT_INDIRECT_QUERY: 909 state = XDM_INDIRECT; 910 break; 911 case XDM_AWAIT_REQUEST_RESPONSE: 912 state = XDM_START_CONNECTION; 913 break; 914 case XDM_AWAIT_MANAGE_RESPONSE: 915 state = XDM_MANAGE; 916 break; 917 case XDM_AWAIT_ALIVE_RESPONSE: 918 state = XDM_KEEPALIVE; 919 break; 920 default: 921 break; 922 } 923 send_packet(); 924} 925 926static int 927XdmcpCheckAuthentication(ARRAY8Ptr Name, ARRAY8Ptr Data, int packet_type) 928{ 929 return (XdmcpARRAY8Equal(Name, AuthenticationName) && 930 (AuthenticationName->length == 0 || 931 (*AuthenticationFuncs->Validator) (AuthenticationData, Data, 932 packet_type))); 933} 934 935static int 936XdmcpAddAuthorization(ARRAY8Ptr name, ARRAY8Ptr data) 937{ 938 AddAuthorFunc AddAuth; 939 940 if (AuthenticationFuncs && AuthenticationFuncs->AddAuth) 941 AddAuth = AuthenticationFuncs->AddAuth; 942 else 943 AddAuth = AddAuthorization; 944 return (*AddAuth) ((unsigned short) name->length, 945 (char *) name->data, 946 (unsigned short) data->length, (char *) data->data); 947} 948 949/* 950 * from here to the end of this file are routines private 951 * to the state machine. 952 */ 953 954static void 955get_xdmcp_sock(void) 956{ 957#ifdef STREAMSCONN 958 struct netconfig *nconf; 959 960 if ((xdmcpSocket = t_open("/dev/udp", O_RDWR, 0)) < 0) { 961 XdmcpWarning("t_open() of /dev/udp failed"); 962 return; 963 } 964 965 if (t_bind(xdmcpSocket, NULL, NULL) < 0) { 966 XdmcpWarning("UDP socket creation failed"); 967 t_error("t_bind(xdmcpSocket) failed"); 968 t_close(xdmcpSocket); 969 return; 970 } 971 972 /* 973 * This part of the code looks contrived. It will actually fit in nicely 974 * when the CLTS part of Xtrans is implemented. 975 */ 976 977 if ((nconf = getnetconfigent("udp")) == NULL) { 978 XdmcpWarning("UDP socket creation failed: getnetconfigent()"); 979 t_unbind(xdmcpSocket); 980 t_close(xdmcpSocket); 981 return; 982 } 983 984 if (netdir_options(nconf, ND_SET_BROADCAST, xdmcpSocket, NULL)) { 985 XdmcpWarning("UDP set broadcast option failed: netdir_options()"); 986 freenetconfigent(nconf); 987 t_unbind(xdmcpSocket); 988 t_close(xdmcpSocket); 989 return; 990 } 991 992 freenetconfigent(nconf); 993#else 994 int soopts = 1; 995 996#if defined(IPv6) && defined(AF_INET6) 997 if ((xdmcpSocket6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) 998 XdmcpWarning("INET6 UDP socket creation failed"); 999#endif 1000 if ((xdmcpSocket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 1001 XdmcpWarning("UDP socket creation failed"); 1002#ifdef SO_BROADCAST 1003 else if (setsockopt(xdmcpSocket, SOL_SOCKET, SO_BROADCAST, (char *) &soopts, 1004 sizeof(soopts)) < 0) 1005 XdmcpWarning("UDP set broadcast socket-option failed"); 1006#endif /* SO_BROADCAST */ 1007 if (xdmcpSocket >= 0 && xdm_from != NULL) { 1008 if (bind(xdmcpSocket, (struct sockaddr *) &FromAddress, 1009 FromAddressLen) < 0) { 1010 FatalError("Xserver: failed to bind to -from address: %s\n", 1011 xdm_from); 1012 } 1013 } 1014#endif /* STREAMSCONN */ 1015} 1016 1017static void 1018send_query_msg(void) 1019{ 1020 XdmcpHeader header; 1021 Bool broadcast = FALSE; 1022 1023#if defined(IPv6) && defined(AF_INET6) 1024 Bool multicast = FALSE; 1025#endif 1026 int i; 1027 int socketfd = xdmcpSocket; 1028 1029 header.version = XDM_PROTOCOL_VERSION; 1030 switch (state) { 1031 case XDM_QUERY: 1032 header.opcode = (CARD16) QUERY; 1033 state = XDM_COLLECT_QUERY; 1034 break; 1035 case XDM_BROADCAST: 1036 header.opcode = (CARD16) BROADCAST_QUERY; 1037 state = XDM_COLLECT_BROADCAST_QUERY; 1038 broadcast = TRUE; 1039 break; 1040#if defined(IPv6) && defined(AF_INET6) 1041 case XDM_MULTICAST: 1042 header.opcode = (CARD16) BROADCAST_QUERY; 1043 state = XDM_COLLECT_MULTICAST_QUERY; 1044 multicast = TRUE; 1045 break; 1046#endif 1047 case XDM_INDIRECT: 1048 header.opcode = (CARD16) INDIRECT_QUERY; 1049 state = XDM_COLLECT_INDIRECT_QUERY; 1050 break; 1051 default: 1052 break; 1053 } 1054 header.length = 1; 1055 for (i = 0; i < AuthenticationNames.length; i++) 1056 header.length += 2 + AuthenticationNames.data[i].length; 1057 1058 XdmcpWriteHeader(&buffer, &header); 1059 XdmcpWriteARRAYofARRAY8(&buffer, &AuthenticationNames); 1060 if (broadcast) { 1061 for (i = 0; i < NumBroadcastAddresses; i++) 1062 XdmcpFlush(xdmcpSocket, &buffer, 1063 (XdmcpNetaddr) &BroadcastAddresses[i], 1064 sizeof(struct sockaddr_in)); 1065 } 1066#if defined(IPv6) && defined(AF_INET6) 1067 else if (multicast) { 1068 struct multicastinfo *mcl; 1069 struct addrinfo *ai; 1070 1071 for (mcl = mcastlist; mcl != NULL; mcl = mcl->next) { 1072 for (ai = mcl->ai; ai != NULL; ai = ai->ai_next) { 1073 if (ai->ai_family == AF_INET) { 1074 unsigned char hopflag = (unsigned char) mcl->hops; 1075 1076 socketfd = xdmcpSocket; 1077 setsockopt(socketfd, IPPROTO_IP, IP_MULTICAST_TTL, 1078 &hopflag, sizeof(hopflag)); 1079 } 1080 else if (ai->ai_family == AF_INET6) { 1081 int hopflag6 = mcl->hops; 1082 1083 socketfd = xdmcpSocket6; 1084 setsockopt(socketfd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, 1085 &hopflag6, sizeof(hopflag6)); 1086 } 1087 else { 1088 continue; 1089 } 1090 XdmcpFlush(socketfd, &buffer, 1091 (XdmcpNetaddr) ai->ai_addr, ai->ai_addrlen); 1092 break; 1093 } 1094 } 1095 } 1096#endif 1097 else { 1098#if defined(IPv6) && defined(AF_INET6) 1099 if (SOCKADDR_FAMILY(ManagerAddress) == AF_INET6) 1100 socketfd = xdmcpSocket6; 1101#endif 1102 XdmcpFlush(socketfd, &buffer, (XdmcpNetaddr) &ManagerAddress, 1103 ManagerAddressLen); 1104 } 1105} 1106 1107static void 1108recv_willing_msg(struct sockaddr *from, int fromlen, unsigned length) 1109{ 1110 ARRAY8 authenticationName; 1111 ARRAY8 hostname; 1112 ARRAY8 status; 1113 1114 authenticationName.data = 0; 1115 hostname.data = 0; 1116 status.data = 0; 1117 if (XdmcpReadARRAY8(&buffer, &authenticationName) && 1118 XdmcpReadARRAY8(&buffer, &hostname) && 1119 XdmcpReadARRAY8(&buffer, &status)) { 1120 if (length == 6 + authenticationName.length + 1121 hostname.length + status.length) { 1122 switch (state) { 1123 case XDM_COLLECT_QUERY: 1124 XdmcpSelectHost(from, fromlen, &authenticationName); 1125 break; 1126 case XDM_COLLECT_BROADCAST_QUERY: 1127#if defined(IPv6) && defined(AF_INET6) 1128 case XDM_COLLECT_MULTICAST_QUERY: 1129#endif 1130 case XDM_COLLECT_INDIRECT_QUERY: 1131 XdmcpAddHost(from, fromlen, &authenticationName, &hostname, 1132 &status); 1133 break; 1134 default: 1135 break; 1136 } 1137 } 1138 } 1139 XdmcpDisposeARRAY8(&authenticationName); 1140 XdmcpDisposeARRAY8(&hostname); 1141 XdmcpDisposeARRAY8(&status); 1142} 1143 1144static void 1145send_request_msg(void) 1146{ 1147 XdmcpHeader header; 1148 int length; 1149 int i; 1150 CARD16 XdmcpConnectionType; 1151 ARRAY8 authenticationData; 1152 int socketfd = xdmcpSocket; 1153 1154 switch (SOCKADDR_FAMILY(ManagerAddress)) { 1155 case AF_INET: 1156 XdmcpConnectionType = FamilyInternet; 1157 break; 1158#if defined(IPv6) && defined(AF_INET6) 1159 case AF_INET6: 1160 XdmcpConnectionType = FamilyInternet6; 1161 break; 1162#endif 1163 default: 1164 XdmcpConnectionType = 0xffff; 1165 break; 1166 } 1167 1168 header.version = XDM_PROTOCOL_VERSION; 1169 header.opcode = (CARD16) REQUEST; 1170 1171 length = 2; /* display number */ 1172 length += 1 + 2 * ConnectionTypes.length; /* connection types */ 1173 length += 1; /* connection addresses */ 1174 for (i = 0; i < ConnectionAddresses.length; i++) 1175 length += 2 + ConnectionAddresses.data[i].length; 1176 authenticationData.length = 0; 1177 authenticationData.data = 0; 1178 if (AuthenticationFuncs) { 1179 (*AuthenticationFuncs->Generator) (AuthenticationData, 1180 &authenticationData, REQUEST); 1181 } 1182 length += 2 + AuthenticationName->length; /* authentication name */ 1183 length += 2 + authenticationData.length; /* authentication data */ 1184 length += 1; /* authorization names */ 1185 for (i = 0; i < AuthorizationNames.length; i++) 1186 length += 2 + AuthorizationNames.data[i].length; 1187 length += 2 + ManufacturerDisplayID.length; /* display ID */ 1188 header.length = length; 1189 1190 if (!XdmcpWriteHeader(&buffer, &header)) { 1191 XdmcpDisposeARRAY8(&authenticationData); 1192 return; 1193 } 1194 XdmcpWriteCARD16(&buffer, DisplayNumber); 1195 XdmcpWriteCARD8(&buffer, ConnectionTypes.length); 1196 1197 /* The connection array is send reordered, so that connections of */ 1198 /* the same address type as the XDMCP manager connection are send */ 1199 /* first. This works around a bug in xdm. mario@klebsch.de */ 1200 for (i = 0; i < (int) ConnectionTypes.length; i++) 1201 if (ConnectionTypes.data[i] == XdmcpConnectionType) 1202 XdmcpWriteCARD16(&buffer, ConnectionTypes.data[i]); 1203 for (i = 0; i < (int) ConnectionTypes.length; i++) 1204 if (ConnectionTypes.data[i] != XdmcpConnectionType) 1205 XdmcpWriteCARD16(&buffer, ConnectionTypes.data[i]); 1206 1207 XdmcpWriteCARD8(&buffer, ConnectionAddresses.length); 1208 for (i = 0; i < (int) ConnectionAddresses.length; i++) 1209 if ((i < ConnectionTypes.length) && 1210 (ConnectionTypes.data[i] == XdmcpConnectionType)) 1211 XdmcpWriteARRAY8(&buffer, &ConnectionAddresses.data[i]); 1212 for (i = 0; i < (int) ConnectionAddresses.length; i++) 1213 if ((i >= ConnectionTypes.length) || 1214 (ConnectionTypes.data[i] != XdmcpConnectionType)) 1215 XdmcpWriteARRAY8(&buffer, &ConnectionAddresses.data[i]); 1216 1217 XdmcpWriteARRAY8(&buffer, AuthenticationName); 1218 XdmcpWriteARRAY8(&buffer, &authenticationData); 1219 XdmcpDisposeARRAY8(&authenticationData); 1220 XdmcpWriteARRAYofARRAY8(&buffer, &AuthorizationNames); 1221 XdmcpWriteARRAY8(&buffer, &ManufacturerDisplayID); 1222#if defined(IPv6) && defined(AF_INET6) 1223 if (SOCKADDR_FAMILY(req_sockaddr) == AF_INET6) 1224 socketfd = xdmcpSocket6; 1225#endif 1226 if (XdmcpFlush(socketfd, &buffer, 1227 (XdmcpNetaddr) &req_sockaddr, req_socklen)) 1228 state = XDM_AWAIT_REQUEST_RESPONSE; 1229} 1230 1231static void 1232recv_accept_msg(unsigned length) 1233{ 1234 CARD32 AcceptSessionID; 1235 ARRAY8 AcceptAuthenticationName, AcceptAuthenticationData; 1236 ARRAY8 AcceptAuthorizationName, AcceptAuthorizationData; 1237 1238 if (state != XDM_AWAIT_REQUEST_RESPONSE) 1239 return; 1240 AcceptAuthenticationName.data = 0; 1241 AcceptAuthenticationData.data = 0; 1242 AcceptAuthorizationName.data = 0; 1243 AcceptAuthorizationData.data = 0; 1244 if (XdmcpReadCARD32(&buffer, &AcceptSessionID) && 1245 XdmcpReadARRAY8(&buffer, &AcceptAuthenticationName) && 1246 XdmcpReadARRAY8(&buffer, &AcceptAuthenticationData) && 1247 XdmcpReadARRAY8(&buffer, &AcceptAuthorizationName) && 1248 XdmcpReadARRAY8(&buffer, &AcceptAuthorizationData)) { 1249 if (length == 12 + AcceptAuthenticationName.length + 1250 AcceptAuthenticationData.length + 1251 AcceptAuthorizationName.length + AcceptAuthorizationData.length) { 1252 if (!XdmcpCheckAuthentication(&AcceptAuthenticationName, 1253 &AcceptAuthenticationData, ACCEPT)) { 1254 XdmcpFatal("Authentication Failure", &AcceptAuthenticationName); 1255 } 1256 /* permit access control manipulations from this host */ 1257 AugmentSelf(&req_sockaddr, req_socklen); 1258 /* if the authorization specified in the packet fails 1259 * to be acceptable, enable the local addresses 1260 */ 1261 if (!XdmcpAddAuthorization(&AcceptAuthorizationName, 1262 &AcceptAuthorizationData)) { 1263 AddLocalHosts(); 1264 } 1265 SessionID = AcceptSessionID; 1266 state = XDM_MANAGE; 1267 send_packet(); 1268 } 1269 } 1270 XdmcpDisposeARRAY8(&AcceptAuthenticationName); 1271 XdmcpDisposeARRAY8(&AcceptAuthenticationData); 1272 XdmcpDisposeARRAY8(&AcceptAuthorizationName); 1273 XdmcpDisposeARRAY8(&AcceptAuthorizationData); 1274} 1275 1276static void 1277recv_decline_msg(unsigned length) 1278{ 1279 ARRAY8 status, DeclineAuthenticationName, DeclineAuthenticationData; 1280 1281 status.data = 0; 1282 DeclineAuthenticationName.data = 0; 1283 DeclineAuthenticationData.data = 0; 1284 if (XdmcpReadARRAY8(&buffer, &status) && 1285 XdmcpReadARRAY8(&buffer, &DeclineAuthenticationName) && 1286 XdmcpReadARRAY8(&buffer, &DeclineAuthenticationData)) { 1287 if (length == 6 + status.length + 1288 DeclineAuthenticationName.length + 1289 DeclineAuthenticationData.length && 1290 XdmcpCheckAuthentication(&DeclineAuthenticationName, 1291 &DeclineAuthenticationData, DECLINE)) { 1292 XdmcpFatal("Session declined", &status); 1293 } 1294 } 1295 XdmcpDisposeARRAY8(&status); 1296 XdmcpDisposeARRAY8(&DeclineAuthenticationName); 1297 XdmcpDisposeARRAY8(&DeclineAuthenticationData); 1298} 1299 1300static void 1301send_manage_msg(void) 1302{ 1303 XdmcpHeader header; 1304 int socketfd = xdmcpSocket; 1305 1306 header.version = XDM_PROTOCOL_VERSION; 1307 header.opcode = (CARD16) MANAGE; 1308 header.length = 8 + DisplayClass.length; 1309 1310 if (!XdmcpWriteHeader(&buffer, &header)) 1311 return; 1312 XdmcpWriteCARD32(&buffer, SessionID); 1313 XdmcpWriteCARD16(&buffer, DisplayNumber); 1314 XdmcpWriteARRAY8(&buffer, &DisplayClass); 1315 state = XDM_AWAIT_MANAGE_RESPONSE; 1316#if defined(IPv6) && defined(AF_INET6) 1317 if (SOCKADDR_FAMILY(req_sockaddr) == AF_INET6) 1318 socketfd = xdmcpSocket6; 1319#endif 1320 XdmcpFlush(socketfd, &buffer, (XdmcpNetaddr) &req_sockaddr, req_socklen); 1321} 1322 1323static void 1324recv_refuse_msg(unsigned length) 1325{ 1326 CARD32 RefusedSessionID; 1327 1328 if (state != XDM_AWAIT_MANAGE_RESPONSE) 1329 return; 1330 if (length != 4) 1331 return; 1332 if (XdmcpReadCARD32(&buffer, &RefusedSessionID)) { 1333 if (RefusedSessionID == SessionID) { 1334 state = XDM_START_CONNECTION; 1335 send_packet(); 1336 } 1337 } 1338} 1339 1340static void 1341recv_failed_msg(unsigned length) 1342{ 1343 CARD32 FailedSessionID; 1344 ARRAY8 status; 1345 1346 if (state != XDM_AWAIT_MANAGE_RESPONSE) 1347 return; 1348 status.data = 0; 1349 if (XdmcpReadCARD32(&buffer, &FailedSessionID) && 1350 XdmcpReadARRAY8(&buffer, &status)) { 1351 if (length == 6 + status.length && SessionID == FailedSessionID) { 1352 XdmcpFatal("Session failed", &status); 1353 } 1354 } 1355 XdmcpDisposeARRAY8(&status); 1356} 1357 1358static void 1359send_keepalive_msg(void) 1360{ 1361 XdmcpHeader header; 1362 int socketfd = xdmcpSocket; 1363 1364 header.version = XDM_PROTOCOL_VERSION; 1365 header.opcode = (CARD16) KEEPALIVE; 1366 header.length = 6; 1367 1368 XdmcpWriteHeader(&buffer, &header); 1369 XdmcpWriteCARD16(&buffer, DisplayNumber); 1370 XdmcpWriteCARD32(&buffer, SessionID); 1371 1372 state = XDM_AWAIT_ALIVE_RESPONSE; 1373#if defined(IPv6) && defined(AF_INET6) 1374 if (SOCKADDR_FAMILY(req_sockaddr) == AF_INET6) 1375 socketfd = xdmcpSocket6; 1376#endif 1377 XdmcpFlush(socketfd, &buffer, (XdmcpNetaddr) &req_sockaddr, req_socklen); 1378} 1379 1380static void 1381recv_alive_msg(unsigned length) 1382{ 1383 CARD8 SessionRunning; 1384 CARD32 AliveSessionID; 1385 1386 if (state != XDM_AWAIT_ALIVE_RESPONSE) 1387 return; 1388 if (length != 5) 1389 return; 1390 if (XdmcpReadCARD8(&buffer, &SessionRunning) && 1391 XdmcpReadCARD32(&buffer, &AliveSessionID)) { 1392 if (SessionRunning && AliveSessionID == SessionID) { 1393 state = XDM_RUN_SESSION; 1394 timeOutTime = GetTimeInMillis() + XDM_DEF_DORMANCY * 1000; 1395 } 1396 else { 1397 XdmcpDeadSession("Alive response indicates session dead"); 1398 } 1399 } 1400} 1401 1402_X_NORETURN 1403static void 1404XdmcpFatal(const char *type, ARRAY8Ptr status) 1405{ 1406 FatalError("XDMCP fatal error: %s %*.*s\n", type, 1407 status->length, status->length, status->data); 1408} 1409 1410static void 1411XdmcpWarning(const char *str) 1412{ 1413 ErrorF("XDMCP warning: %s\n", str); 1414} 1415 1416static void 1417get_addr_by_name(const char *argtype, 1418 const char *namestr, 1419 int port, 1420 int socktype, SOCKADDR_TYPE * addr, SOCKLEN_TYPE * addrlen 1421#if defined(IPv6) && defined(AF_INET6) 1422 , struct addrinfo **aip, struct addrinfo **aifirstp 1423#endif 1424 ) 1425{ 1426#if defined(IPv6) && defined(AF_INET6) 1427 struct addrinfo *ai; 1428 struct addrinfo hints; 1429 char portstr[6]; 1430 char *pport = portstr; 1431 int gaierr; 1432 1433 memset(&hints, 0, sizeof(hints)); 1434 hints.ai_socktype = socktype; 1435 1436 if (port == 0) { 1437 pport = NULL; 1438 } 1439 else if (port > 0 && port < 65535) { 1440 snprintf(portstr, sizeof(portstr), "%d", port); 1441 } 1442 else { 1443 FatalError("Xserver: port out of range: %d\n", port); 1444 } 1445 1446 if (*aifirstp != NULL) { 1447 freeaddrinfo(*aifirstp); 1448 *aifirstp = NULL; 1449 } 1450 1451 if ((gaierr = getaddrinfo(namestr, pport, &hints, aifirstp)) == 0) { 1452 for (ai = *aifirstp; ai != NULL; ai = ai->ai_next) { 1453 if (ai->ai_family == AF_INET || ai->ai_family == AF_INET6) 1454 break; 1455 } 1456 if ((ai == NULL) || (ai->ai_addrlen > sizeof(SOCKADDR_TYPE))) { 1457 FatalError("Xserver: %s host %s not on supported network type\n", 1458 argtype, namestr); 1459 } 1460 else { 1461 *aip = ai; 1462 *addrlen = ai->ai_addrlen; 1463 memcpy(addr, ai->ai_addr, ai->ai_addrlen); 1464 } 1465 } 1466 else { 1467 FatalError("Xserver: %s: %s %s\n", gai_strerror(gaierr), argtype, 1468 namestr); 1469 } 1470#else 1471 struct hostent *hep; 1472 1473#ifdef XTHREADS_NEEDS_BYNAMEPARAMS 1474 _Xgethostbynameparams hparams; 1475#endif 1476#if defined(WIN32) && defined(TCPCONN) 1477 _XSERVTransWSAStartup(); 1478#endif 1479 if (!(hep = _XGethostbyname(namestr, hparams))) { 1480 FatalError("Xserver: %s unknown host: %s\n", argtype, namestr); 1481 } 1482 if (hep->h_length == sizeof(struct in_addr)) { 1483 memmove(&addr->sin_addr, hep->h_addr, hep->h_length); 1484 *addrlen = sizeof(struct sockaddr_in); 1485 addr->sin_family = AF_INET; 1486 addr->sin_port = htons(port); 1487 } 1488 else { 1489 FatalError("Xserver: %s host on strange network %s\n", argtype, 1490 namestr); 1491 } 1492#endif 1493} 1494 1495static void 1496get_manager_by_name(int argc, char **argv, int i) 1497{ 1498 1499 if ((i + 1) == argc) { 1500 FatalError("Xserver: missing %s host name in command line\n", argv[i]); 1501 } 1502 1503 get_addr_by_name(argv[i], argv[i + 1], xdm_udp_port, SOCK_DGRAM, 1504 &ManagerAddress, &ManagerAddressLen 1505#if defined(IPv6) && defined(AF_INET6) 1506 , &mgrAddr, &mgrAddrFirst 1507#endif 1508 ); 1509} 1510 1511static void 1512get_fromaddr_by_name(int argc, char **argv, int i) 1513{ 1514#if defined(IPv6) && defined(AF_INET6) 1515 struct addrinfo *ai = NULL; 1516 struct addrinfo *aifirst = NULL; 1517#endif 1518 if (i == argc) { 1519 FatalError("Xserver: missing -from host name in command line\n"); 1520 } 1521 get_addr_by_name("-from", argv[i], 0, 0, &FromAddress, &FromAddressLen 1522#if defined(IPv6) && defined(AF_INET6) 1523 , &ai, &aifirst 1524#endif 1525 ); 1526#if defined(IPv6) && defined(AF_INET6) 1527 if (aifirst != NULL) 1528 freeaddrinfo(aifirst); 1529#endif 1530 xdm_from = argv[i]; 1531} 1532 1533#if defined(IPv6) && defined(AF_INET6) 1534static int 1535get_mcast_options(int argc, char **argv, int i) 1536{ 1537 const char *address = XDM_DEFAULT_MCAST_ADDR6; 1538 int hopcount = 1; 1539 struct addrinfo hints; 1540 char portstr[6]; 1541 int gaierr; 1542 struct addrinfo *ai, *firstai; 1543 1544 if ((i < argc) && (argv[i][0] != '-') && (argv[i][0] != '+')) { 1545 address = argv[i++]; 1546 if ((i < argc) && (argv[i][0] != '-') && (argv[i][0] != '+')) { 1547 hopcount = strtol(argv[i++], NULL, 10); 1548 if ((hopcount < 1) || (hopcount > 255)) { 1549 FatalError("Xserver: multicast hop count out of range: %d\n", 1550 hopcount); 1551 } 1552 } 1553 } 1554 1555 if (xdm_udp_port > 0 && xdm_udp_port < 65535) { 1556 snprintf(portstr, sizeof(portstr), "%d", xdm_udp_port); 1557 } 1558 else { 1559 FatalError("Xserver: port out of range: %d\n", xdm_udp_port); 1560 } 1561 memset(&hints, 0, sizeof(hints)); 1562 hints.ai_socktype = SOCK_DGRAM; 1563 1564 if ((gaierr = getaddrinfo(address, portstr, &hints, &firstai)) == 0) { 1565 for (ai = firstai; ai != NULL; ai = ai->ai_next) { 1566 if (((ai->ai_family == AF_INET) && 1567 IN_MULTICAST(((struct sockaddr_in *) ai->ai_addr) 1568 ->sin_addr.s_addr)) 1569 || ((ai->ai_family == AF_INET6) && 1570 IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6 *) ai->ai_addr) 1571 ->sin6_addr))) 1572 break; 1573 } 1574 if (ai == NULL) { 1575 FatalError("Xserver: address not supported multicast type %s\n", 1576 address); 1577 } 1578 else { 1579 struct multicastinfo *mcastinfo, *mcl; 1580 1581 mcastinfo = malloc(sizeof(struct multicastinfo)); 1582 mcastinfo->next = NULL; 1583 mcastinfo->ai = firstai; 1584 mcastinfo->hops = hopcount; 1585 1586 if (mcastlist == NULL) { 1587 mcastlist = mcastinfo; 1588 } 1589 else { 1590 for (mcl = mcastlist; mcl->next != NULL; mcl = mcl->next) { 1591 /* Do nothing - just find end of list */ 1592 } 1593 mcl->next = mcastinfo; 1594 } 1595 } 1596 } 1597 else { 1598 FatalError("Xserver: %s: %s\n", gai_strerror(gaierr), address); 1599 } 1600 return i; 1601} 1602#endif 1603 1604#else 1605static int xdmcp_non_empty; /* avoid complaint by ranlib */ 1606#endif /* XDMCP */ 1607