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