main.c revision b3078add
1 2/* 3Copyright 1996, 1998 The Open Group 4 5Permission to use, copy, modify, distribute, and sell this software and its 6documentation for any purpose is hereby granted without fee, provided that 7the above copyright notice appear in all copies and that both that 8copyright notice and this permission notice appear in supporting 9documentation. 10 11The above copyright notice and this permission notice shall be included 12in all copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 18OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20OTHER DEALINGS IN THE SOFTWARE. 21 22Except as contained in this notice, the name of The Open Group shall 23not be used in advertising or otherwise to promote the sale, use or 24other dealings in this Software without prior written authorization 25from The Open Group. 26*/ 27 28#include <stdlib.h> 29#include "pmint.h" 30#include <X11/StringDefs.h> 31#include <X11/Intrinsic.h> 32#include <X11/ICE/ICEmsg.h> 33#include <X11/ICE/ICEproto.h> 34#include <X11/PM/PMproto.h> 35#include <X11/PM/PM.h> 36#include "pmdb.h" 37#include "config.h" 38#include <assert.h> 39 40#include <netinet/in.h> 41#include <arpa/inet.h> 42#include <sys/socket.h> 43#include <netdb.h> 44 45static int PMprotocolSetupProc ( IceConn iceConn, int majorVersion, 46 int minorVersion, char *vendor, 47 char *release, IcePointer *clientDataRet, 48 char **failureReasonRet ); 49static void SendGetProxyAddr ( PMconn *pmConn, char *serviceName, 50 char *serverAddress, char *hostAddress, 51 char *startOptions, int authLen, 52 char *authName, char *authData ); 53 54static int PMAcceptorOpcode; 55static int PMOriginatorOpcode; 56 57static int PMversionCount = 1; 58static IcePaVersionRec PMReplyVersions[] = {{PM_MAJOR_VERSION, PM_MINOR_VERSION, 59 PMReplyProcessMessages}}; 60static IcePoVersionRec PMSetupVersions[] = {{PM_MAJOR_VERSION, PM_MINOR_VERSION, 61 PMSetupProcessMessages}}; 62 63char *PM_VENDOR_STRING = XVENDORNAME; 64char *PM_VENDOR_RELEASE = XORG_RELEASE; 65 66int verbose = 0; 67 68static XtAppContext appContext; 69 70#define PM_PORT "6500" 71 72static char *configFile = NULL; 73 74void 75Usage(void) 76{ 77 fprintf (stderr, "Usage: proxymngr [-config file] [-verbose]\n"); 78 exit (1); 79} 80 81void 82SetCloseOnExec(int fd) 83{ 84#ifdef F_SETFD 85#ifdef FD_CLOEXEC 86 (void) fcntl (fd, F_SETFD, FD_CLOEXEC); 87#else 88 (void) fcntl (fd, F_SETFD, 1); 89#endif /* FD_CLOEXEC */ 90#endif /* F_SETFD */ 91} 92 93/* 94 * Main program 95 */ 96 97int 98main (int argc, char *argv[]) 99{ 100 IceListenObj *listenObjs; 101 int numTransports, i; 102 char errormsg[256]; 103 char *networkIds, *p; 104 105 for (i = 1; i < argc; i++) 106 { 107 if (strcmp (argv[i], "-config") == 0) 108 { 109 if (++i < argc) 110 configFile = argv[i]; 111 else 112 Usage (); 113 } 114 else if (strcmp(argv[i], "-verbose") == 0) 115 { 116 verbose = 1; 117 } 118 else 119 Usage (); 120 } 121 122 if (!configFile) 123 configFile = CONFIG_FILE; 124 125 if (verbose) 126 fprintf (stderr, "config file = %s\n", configFile); 127 128 /* 129 * Install an IO error handler. 130 */ 131 InstallIOErrorHandler (); 132 133 /* 134 * Register support for PROXY_MANAGEMENT. 135 */ 136 137 /* For Managed proxies, the proxy does the Setup */ 138 if ((PMAcceptorOpcode = IceRegisterForProtocolReply ( 139 PM_PROTOCOL_NAME, PM_VENDOR_STRING, PM_VENDOR_RELEASE, 140 PMversionCount, PMReplyVersions, 141 0, /* authcount */ 142 NULL, /* authnames */ 143 NULL, /* authprocs */ 144 HostBasedAuthProc, 145 PMprotocolSetupProc, 146 NULL, /* protocolActivateProc */ 147 NULL /* IceIOErrorProc */ )) < 0) 148 { 149 fprintf (stderr, 150 "Could not register PROXY_MANAGEMENT protocol reply with ICE"); 151 exit (1); 152 } 153 154 /* For Unmanaged proxies, we do the Setup 155 * ICElib doesn't specify that the same opCode will be returned 156 * so don't bet on it. 157 */ 158 if ((PMOriginatorOpcode = IceRegisterForProtocolSetup ( 159 PM_PROTOCOL_NAME, PM_VENDOR_STRING, PM_VENDOR_RELEASE, 160 PMversionCount, PMSetupVersions, 161 0, /* authcount */ 162 NULL, /* authnames */ 163 NULL, /* authprocs */ 164 NULL /* IceIOErrorProc */ )) < 0) 165 { 166 fprintf (stderr, 167 "Could not register PROXY_MANAGEMENT protocol setup with ICE"); 168 exit (1); 169 } 170 171 172 if (!IceListenForWellKnownConnections ( 173 PM_PORT, &numTransports, &listenObjs, 256, errormsg)) 174 { 175 fprintf (stderr, "%s\n", errormsg); 176 exit (1); 177 } 178 179 networkIds = IceComposeNetworkIdList (numTransports, listenObjs); 180 p = (char *) malloc(sizeof ("PROXY_MANAGER") + strlen(networkIds) + 2); 181 sprintf (p, "PROXY_MANAGER=%s", networkIds); 182 putenv (p); 183 printf ("%s\n", p); 184 free (networkIds); 185 186 appContext = XtCreateApplicationContext (); 187 188 InitWatchProcs (appContext); 189 190 for (i = 0; i < numTransports; i++) 191 { 192 XtAppAddInput (appContext, 193 IceGetListenConnectionNumber (listenObjs[i]), 194 (XtPointer) XtInputReadMask, 195 NewConnectionXtProc, (XtPointer) listenObjs[i]); 196 197 IceSetHostBasedAuthProc (listenObjs[i], HostBasedAuthProc); 198 199 SetCloseOnExec (IceGetListenConnectionNumber (listenObjs[i])); 200 } 201 202 /* 203 * Main loop 204 */ 205 XtAppMainLoop (appContext); 206 exit (0); 207} 208 209 210/* 211 * Xt callback invoked when a client attempts to connect. 212 */ 213 214/* ARGSUSED */ 215void 216NewConnectionXtProc(XtPointer client_data, int *source, XtInputId *id) 217{ 218 IceConn ice_conn; 219 char *connstr; 220 IceAcceptStatus status; 221 222 ice_conn = IceAcceptConnection((IceListenObj) client_data, &status); 223 if (! ice_conn) { 224 if (verbose) 225 printf ("IceAcceptConnection failed\n"); 226 } else { 227 IceConnectStatus cstatus; 228 229 /* 230 * Mark this fd to be closed upon exec 231 */ 232 SetCloseOnExec (IceConnectionNumber (ice_conn)); 233 234 while ((cstatus = IceConnectionStatus (ice_conn))==IceConnectPending) { 235 XtAppProcessEvent (appContext, XtIMAll); 236 } 237 238 if (cstatus == IceConnectAccepted) { 239 if (verbose) { 240 printf ("ICE Connection opened by client, IceConn fd = %d, ", 241 IceConnectionNumber (ice_conn)); 242 connstr = IceConnectionString (ice_conn); 243 printf ("Accept at networkId %s\n", connstr); 244 free (connstr); 245 printf ("\n"); 246 } 247 } else { 248 if (verbose) 249 { 250 if (cstatus == IceConnectIOError) 251 printf ("IO error opening ICE Connection!\n"); 252 else 253 printf ("ICE Connection rejected!\n"); 254 } 255 256 IceCloseConnection (ice_conn); 257 } 258 } 259} 260 261 262/* 263 * See ConnectToProxy() if you change any of the pmConn structure 264 */ 265static Status 266PMprotocolSetupProc(IceConn iceConn, int majorVersion, int minorVersion, 267 char *vendor, char *release, IcePointer *clientDataRet, 268 char **failureReasonRet) 269 270{ 271 /* 272 * Allocate new pmConn. 273 */ 274 275 static char standardError[] = "Could not allocate memory for new client"; 276 PMconn *pmConn; 277 278 if ((pmConn = (PMconn *) malloc (sizeof (PMconn))) == NULL) 279 { 280 if (verbose) 281 fprintf (stderr, "%s\n", standardError); 282 283 *failureReasonRet = standardError; 284 return (0); 285 } 286 287 pmConn->iceConn = iceConn; 288 pmConn->pmOpcode = PMAcceptorOpcode; 289 pmConn->proto_major_version = majorVersion; 290 pmConn->proto_minor_version = minorVersion; 291 pmConn->vendor = vendor; 292 pmConn->release = release; 293 294 *clientDataRet = (IcePointer) pmConn; 295 296 return (1); 297} 298 299 300static void 301SendGetProxyAddr ( 302 PMconn *pmConn, 303 char *serviceName, 304 char *serverAddress, 305 char *hostAddress, 306 char *startOptions, 307 int authLen, 308 char *authName, 309 char *authData) 310 311{ 312 IceConn iceConn = pmConn->iceConn; 313 pmGetProxyAddrMsg *pMsg; 314 char *pData; 315 int len; 316 317 if (verbose) { 318 printf ("Sending GetProxyAddr to proxy %d, serviceName = %s, serverAddr = %s\n", 319 IceConnectionNumber(iceConn), serviceName, serverAddress); 320 printf (" hostAddr = %s, options = %s, authLen = %d\n", 321 hostAddress ? hostAddress : "", 322 startOptions ? startOptions : "", 323 authLen); 324 if (authLen > 0) 325 printf (" authName = %s\n", authName); 326 } 327 328 len = STRING_BYTES (serviceName) + 329 STRING_BYTES (serverAddress) + 330 STRING_BYTES (hostAddress) + 331 STRING_BYTES (startOptions) + 332 (authLen > 0 ? (STRING_BYTES (authName) + authLen) : 0); 333 334 IceGetHeaderExtra (iceConn, pmConn->pmOpcode, PM_GetProxyAddr, 335 SIZEOF (pmGetProxyAddrMsg), WORD64COUNT (len), 336 pmGetProxyAddrMsg, pMsg, pData); 337 338 pMsg->authLen = authLen; 339 340 STORE_STRING (pData, serviceName); 341 STORE_STRING (pData, serverAddress); 342 STORE_STRING (pData, hostAddress); 343 STORE_STRING (pData, startOptions); 344 if (authLen > 0) 345 { 346 STORE_STRING (pData, authName); 347 memcpy (pData, authData, authLen); 348 } 349 350 IceFlush (iceConn); 351} 352 353 354void 355SendGetProxyAddrReply ( 356 PMconn *requestor, 357 int status, 358 char *addr, 359 char *error) 360 361{ 362 int len = STRING_BYTES (addr) + STRING_BYTES (error); 363 pmGetProxyAddrReplyMsg *pReply; 364 char *pData; 365 366 if (verbose) { 367 fputs ("Replying with ", stderr); 368 fputs (status == PM_Success ? "Success: " : 369 status == PM_Failure ? "Failure: " : 370 status == PM_Unable ? "Unable: " : 371 "?unknown status", stderr); 372 fputs (status == PM_Success ? addr : error, stderr); 373 fputc ('\n', stderr); 374 } 375 376 IceGetHeaderExtra (requestor->iceConn, 377 requestor->pmOpcode, PM_GetProxyAddrReply, 378 SIZEOF (pmGetProxyAddrReplyMsg), WORD64COUNT (len), 379 pmGetProxyAddrReplyMsg, pReply, pData); 380 381 pReply->status = status; 382 383 STORE_STRING (pData, addr); 384 STORE_STRING (pData, error); 385 386 IceFlush (requestor->iceConn); 387} 388 389 390 391void 392PMReplyProcessMessages(IceConn iceConn, IcePointer clientData, int opcode, 393 unsigned long length, Bool swap) 394 395{ 396 PMconn *pmConn = (PMconn *) clientData; 397 398 assert(pmConn->iceConn == iceConn); 399 400 switch (opcode) 401 { 402 case PM_GetProxyAddr: 403 { 404 pmGetProxyAddrMsg *pMsg; 405 char *pData, *pStart; 406 char *serviceName = NULL, *serverAddress = NULL; 407 char *hostAddress = NULL, *startOptions = NULL; 408 char *authName = NULL, *authData = NULL; 409 int authLen; 410 411#if 0 /* No-op */ 412 CHECK_AT_LEAST_SIZE (iceConn, pmConn->pmOpcode, opcode, 413 length, SIZEOF (pmGetProxyAddrMsg), IceFatalToProtocol); 414#endif 415 416 IceReadCompleteMessage (iceConn, SIZEOF (pmGetProxyAddrMsg), 417 pmGetProxyAddrMsg, pMsg, pStart); 418 419 if (!IceValidIO (iceConn)) 420 { 421 IceDisposeCompleteMessage (iceConn, pStart); 422 return; 423 } 424 425 authLen = swap ? lswaps (pMsg->authLen) : pMsg->authLen; 426 427 pData = pStart; 428 429 SKIP_STRING (pData, swap); /* proxy-service */ 430 SKIP_STRING (pData, swap); /* server-address */ 431 SKIP_STRING (pData, swap); /* host-address */ 432 SKIP_STRING (pData, swap); /* start-options */ 433 if (authLen > 0) 434 { 435 SKIP_STRING (pData, swap); /* auth-name */ 436 pData += (authLen + PAD64 (authLen)); /* auth-data */ 437 } 438 439 CHECK_COMPLETE_SIZE (iceConn, pmConn->pmOpcode, opcode, 440 length, pData - pStart + SIZEOF (pmGetProxyAddrMsg), 441 pStart, IceFatalToProtocol); 442 443 pData = pStart; 444 445 EXTRACT_STRING (pData, swap, serviceName); 446 EXTRACT_STRING (pData, swap, serverAddress); 447 EXTRACT_STRING (pData, swap, hostAddress); 448 EXTRACT_STRING (pData, swap, startOptions); 449 if (authLen > 0) 450 { 451 EXTRACT_STRING (pData, swap, authName); 452 authData = (char *) malloc (authLen); 453 memcpy (authData, pData, authLen); 454 } 455 456 if (serverAddress) 457 { 458 /* 459 * Assume that if serverAddress is something like :0 or :0.0 460 * then the request is for a server on the client's host. 461 * 462 * However, the proxy handling this request may be on a 463 * different host than the client or the client host, 464 * proxy host and the server host may all be different, 465 * thus a serverAddress of :0 or :0.0 is not useful. 466 * Therefore, change serverAddress to use the client's 467 * hostname. 468 */ 469 char *tmpName; 470 471 tmpName = strrchr (serverAddress, ':'); 472 473 if (tmpName && ((tmpName == serverAddress) || 474 (!strncmp (serverAddress, "unix:", 5)))) 475 { 476#if defined(IPv6) && defined(AF_INET6) 477 struct sockaddr_storage serverSock; 478#else 479 struct sockaddr_in serverSock; 480#endif 481 int retVal; 482 int addrLen = sizeof(serverSock); 483 484 retVal = getpeername(IceConnectionNumber(iceConn), 485 (struct sockaddr *) &serverSock, 486 (void *) &addrLen); 487 if (!retVal) 488 { 489 char *canonname = NULL; 490#if defined(IPv6) && defined(AF_INET6) 491 char hostname[NI_MAXHOST]; 492 struct addrinfo *ai = NULL, hints; 493 494 if (getnameinfo((struct sockaddr *) &serverSock, 495 addrLen, hostname, sizeof(hostname), NULL, 0, 0) == 0) { 496 (void)memset(&hints, 0, sizeof(hints)); 497 hints.ai_flags = AI_CANONNAME; 498 if (getaddrinfo(hostname, NULL, &hints, &ai) == 0) { 499 canonname = ai->ai_canonname; 500 } 501 } 502#else 503 struct hostent *hostent; 504 505 hostent = gethostbyname (inet_ntoa(serverSock.sin_addr)); 506 507 if (hostent && hostent->h_name) 508 canonname = hostent->h_name; 509#endif 510 if (canonname) 511 { 512 int len; 513 char * pch = strdup (tmpName); 514 515 len = strlen(canonname) + strlen(tmpName) + 1; 516 serverAddress = (char *) realloc (serverAddress, len); 517 sprintf (serverAddress, "%s%s", canonname, pch); 518 free (pch); 519 } 520#if defined(IPv6) && defined(AF_INET6) 521 if (ai != NULL) 522 freeaddrinfo(ai); 523#endif 524 } 525 } 526 } 527 528 if (verbose) { 529 printf ("Got GetProxyAddr, serviceName = %s, serverAddr = %s\n", 530 serviceName, serverAddress); 531 printf (" hostAddr = %s, options = %s, authLen = %d\n", 532 hostAddress, startOptions, authLen); 533 if (authLen > 0) 534 printf (" authName = %s\n", authName); 535 } 536 537 IceDisposeCompleteMessage (iceConn, pStart); 538 539 ForwardRequest (pmConn, serviceName, serverAddress, hostAddress, 540 startOptions, authLen, authName, authData); 541 542 if (serviceName) 543 free (serviceName); 544 if (serverAddress) 545 free (serverAddress); 546 if (hostAddress) 547 free (hostAddress); 548 if (startOptions) 549 free (startOptions); 550 if (authName) 551 free (authName); 552 if (authData) 553 free (authData); 554 555 break; 556 } 557 558 case PM_StartProxy: 559 { 560 pmStartProxyMsg *pMsg; 561 char *pData, *pStart; 562 char *serviceName = NULL; 563 char *serverAddress; 564 char *hostAddress; 565 char *startOptions; 566 int authLen; 567 char *authName; 568 char *authData; 569 570#if 0 /* No-op */ 571 CHECK_AT_LEAST_SIZE (iceConn, pmConn->pmOpcode, opcode, 572 length, SIZEOF (pmStartProxyMsg), IceFatalToProtocol); 573#endif 574 575 IceReadCompleteMessage (iceConn, SIZEOF (pmStartProxyMsg), 576 pmStartProxyMsg, pMsg, pStart); 577 578 if (!IceValidIO (iceConn)) 579 { 580 IceDisposeCompleteMessage (iceConn, pStart); 581 return; 582 } 583 584 pData = pStart; 585 586 SKIP_STRING (pData, swap); /* proxy-service */ 587 588 CHECK_COMPLETE_SIZE (iceConn, pmConn->pmOpcode, opcode, 589 length, pData - pStart + SIZEOF (pmStartProxyMsg), 590 pStart, IceFatalToProtocol); 591 592 pData = pStart; 593 594 EXTRACT_STRING (pData, swap, serviceName); 595 596 assert(serviceName); 597 598 if (verbose) 599 printf ("Got StartProxy on fd %d, serviceName = %s\n", 600 IceConnectionNumber(iceConn), serviceName); 601 602 IceDisposeCompleteMessage (iceConn, pStart); 603 604 if (! ActivateProxyService (serviceName, pmConn)) { 605 fputs ("Configuration error: received unexpected StartProxy for service ", stderr); 606 fputs (serviceName, stderr); 607 fputc ('\n', stderr); 608 IceCloseConnection (iceConn); 609 } 610 else { 611 612 /* 613 * Now send the GetProxyAddr message to the proxy. 614 */ 615 if (PeekRequestorQueue(pmConn, 616 NULL, NULL, NULL, 617 &serverAddress, &hostAddress, &startOptions, 618 &authLen, &authName, &authData)) { 619 SendGetProxyAddr(pmConn, 620 serviceName, serverAddress, 621 hostAddress, startOptions, 622 authLen, authName, authData); 623 } 624 else if (verbose) { 625 fputs ("Received StartProxy for service ", stderr); 626 fputs (serviceName, stderr); 627 fputs (" but no waiting GetproxyAddr requests\n", stderr); 628 } 629 } 630 631 free (serviceName); 632 633 break; 634 } 635 636 case PM_GetProxyAddrReply: 637 638 { 639 pmGetProxyAddrReplyMsg *pMsg; 640 char *pData, *pStart; 641 char *addr = NULL, *error = NULL; 642 643#if 0 /* No-op */ 644 CHECK_AT_LEAST_SIZE (iceConn, pmConn->pmOpcode, opcode, 645 length, SIZEOF (pmGetProxyAddrReplyMsg), IceFatalToProtocol); 646#endif 647 648 IceReadCompleteMessage (iceConn, SIZEOF (pmGetProxyAddrReplyMsg), 649 pmGetProxyAddrReplyMsg, pMsg, pStart); 650 651 if (!IceValidIO (iceConn)) 652 { 653 IceDisposeCompleteMessage (iceConn, pStart); 654 return; 655 } 656 657 pData = pStart; 658 659 SKIP_STRING (pData, swap); /* proxy-address */ 660 SKIP_STRING (pData, swap); /* failure-reason */ 661 662 CHECK_COMPLETE_SIZE (iceConn, pmConn->pmOpcode, opcode, 663 length, pData - pStart + SIZEOF (pmGetProxyAddrReplyMsg), 664 pStart, IceFatalToProtocol); 665 666 pData = pStart; 667 668 EXTRACT_STRING (pData, swap, addr); 669 EXTRACT_STRING (pData, swap, error); 670 671 if (verbose) { 672 printf ("Got GetProxyAddrReply from proxy %d, status = %d, ", 673 IceConnectionNumber(iceConn), pMsg->status); 674 if (pMsg->status == PM_Success) 675 printf ("addr = %s\n", addr); 676 else 677 printf ("error = %s\n", error); 678 } 679 680 { /* Ignore any unsolicited replies so we don't get further confused */ 681 running_proxy *proxy = ProxyForPMconn(pmConn); 682 683 if (!proxy || !proxy->requests) 684 { 685 if (verbose) 686 fprintf (stderr, "Received unsolicited GetProxyAddrReply from proxy %d; ignoring it.\n", 687 IceConnectionNumber(iceConn)); 688 689 IceDisposeCompleteMessage (iceConn, pStart); 690 break; 691 } 692 } 693 694 switch (pMsg->status) { 695 696 case PM_Success: 697 { 698 /* 699 * Now send the GetProxyAddr reply to xfindproxy. 700 */ 701 702 SendGetProxyAddrReply ( 703 PopRequestorQueue (pmConn, True, True /* free proxy list */), 704 PM_Success /* status */, addr, NULL); 705 706 break; 707 } 708 709 case PM_Unable: 710 { 711 running_proxy_list *proxyList; 712 char *serviceName, *serverAddress, *hostAddress, *startOptions; 713 PMconn *requestor; 714 int authLen; 715 char *authName; 716 char *authData; 717 718 { 719 running_proxy *proxy = ProxyForPMconn(pmConn); 720 if (proxy) 721 proxy->refused_service = True; 722 else 723 fputs("Internal error: received GetProxyAddrReply from an unknown proxy\n", stderr); 724 } 725 726 if (! PeekRequestorQueue (pmConn, &requestor, 727 &proxyList, &serviceName, &serverAddress, 728 &hostAddress, &startOptions, 729 &authLen, &authName, &authData)) { 730 if (verbose) 731 fputs("Received GetProxyAddrReply from a proxy with no requests\n", stderr); 732 733 proxyList = NULL; 734 serviceName = "?unknown service--internal error"; 735 } 736 737 if (proxyList && (proxyList->current < proxyList->count - 1)) 738 { 739 /* 740 * Ask the next running proxy if it can service this request. 741 */ 742 running_proxy *nextProxy; 743 744 proxyList->current++; 745 nextProxy = proxyList->list[proxyList->current]; 746 747 if (nextProxy->pmConn != NULL) { 748 /* send only if the proxy has started */ 749 SendGetProxyAddr (nextProxy->pmConn, serviceName, 750 serverAddress, hostAddress, startOptions, 751 authLen, authName, authData); 752 } 753 754 PushRequestorQueue (nextProxy, requestor, proxyList, 755 serviceName, serverAddress, hostAddress, startOptions, 756 authLen, authName, authData); 757 758 PopRequestorQueue (pmConn, False, False); 759 } 760 else 761 { 762 /* 763 * Start a new proxy. 764 */ 765 766 running_proxy *runningProxy = NULL; 767 char *startCommand; 768 char *proxyAddress; 769 Bool managed; 770 771 if (!GetConfig (configFile, serviceName, &managed, 772 &startCommand, &proxyAddress)) 773 { 774 SendGetProxyAddrReply (requestor, PM_Failure, 775 NULL, "Could not read proxy manager config file"); 776 } 777 else 778 { 779 runningProxy = StartNewProxy (serviceName, startCommand); 780 781 if (runningProxy) 782 { 783 PushRequestorQueue (runningProxy, 784 requestor, proxyList, 785 serviceName, serverAddress, 786 hostAddress, startOptions, 787 authLen, authName, authData); 788 } 789 else 790 { 791 SendGetProxyAddrReply (pmConn, PM_Failure, 792 NULL, "Can't start new proxy"); 793 } 794 } 795 796 if (startCommand) 797 free (startCommand); 798 if (proxyAddress) 799 free (proxyAddress); 800 801 PopRequestorQueue (pmConn, False, 802 runningProxy ? False : True /* free proxy list */); 803 } 804 break; 805 } 806 807 default: 808 if (verbose && pMsg->status != PM_Unable) 809 fprintf(stderr, 810 "Error: proxy returned unrecognized status: %d\n", 811 pMsg->status); 812 /* FALLTHROUGH */ 813 814 case PM_Failure: 815 SendGetProxyAddrReply ( 816 PopRequestorQueue (pmConn, True, True /* free proxy list */), 817 pMsg->status, NULL, error); 818 } 819 820 IceDisposeCompleteMessage (iceConn, pStart); 821 822 /* see if there was more work queued for this proxy */ 823 { 824 char *serviceName, *serverAddress, *hostAddress, *startOptions; 825 int authLen; 826 char *authName, *authData; 827 828 if (PeekRequestorQueue(pmConn, 829 NULL, NULL, &serviceName, 830 &serverAddress, &hostAddress, &startOptions, 831 &authLen, &authName, &authData)) { 832 SendGetProxyAddr(pmConn, 833 serviceName, serverAddress, 834 hostAddress, startOptions, 835 authLen, authName, authData); 836 } 837 } 838 839 if (addr) 840 free (addr); 841 if (error) 842 free (error); 843 844 break; 845 } 846 847 case PM_Error: 848 { 849 iceErrorMsg *pMsg; 850 char *pStart; 851 852 CHECK_AT_LEAST_SIZE (iceConn, pmConn->pmOpcode, PM_Error, length, 853 sizeof(iceErrorMsg), IceFatalToProtocol); 854 855 IceReadCompleteMessage (iceConn, SIZEOF (iceErrorMsg), 856 iceErrorMsg, pMsg, pStart); 857 858 if (!IceValidIO (iceConn)) 859 { 860 IceDisposeCompleteMessage (iceConn, pStart); 861 return; 862 } 863 864 if (swap) 865 { 866 pMsg->errorClass = lswaps (pMsg->errorClass); 867 pMsg->offendingSequenceNum = lswapl (pMsg->offendingSequenceNum); 868 } 869 870 fprintf(stderr, "Received ICE Error: class=0x%x\n offending minor opcode=%d, severity=%d, sequence=%d\n", 871 pMsg->errorClass, pMsg->offendingMinorOpcode, pMsg->severity, 872 (int)pMsg->offendingSequenceNum); 873 874 IceDisposeCompleteMessage (iceConn, pStart); 875 876 break; 877 } 878 879 default: 880 { 881 _IceErrorBadMinor (iceConn, pmConn->pmOpcode, opcode, IceCanContinue); 882 _IceReadSkip (iceConn, length << 3); 883 break; 884 } 885 } 886} 887 888void 889PMSetupProcessMessages(IceConn iceConn, IcePointer clientData, int opcode, 890 unsigned long length, Bool swap, 891 IceReplyWaitInfo *replyWait, Bool *replyReadyRet) 892 893{ 894 assert (replyWait == NULL); 895 896 PMReplyProcessMessages (iceConn, clientData, opcode, length, swap); 897} 898 899 900void 901ForwardRequest(PMconn *requestor, char *serviceName, char *serverAddress, 902 char *hostAddress, char *startOptions, int authLen, 903 char *authName, char *authData) 904{ 905 running_proxy_list *proxyList; 906 running_proxy *runningProxy = NULL; 907 int pushRequest = 0; 908 909 if ((proxyList = GetRunningProxyList ( 910 serviceName, serverAddress)) != NULL) 911 { 912 while (proxyList->current < proxyList->count) { 913 runningProxy = proxyList->list[proxyList->current]; 914 915 if (runningProxy->pmConn != NULL) { 916 SendGetProxyAddr (runningProxy->pmConn, serviceName, 917 serverAddress, hostAddress, NULL, 918 authLen, authName, authData); 919 break; 920 } 921 proxyList->current++; 922 } 923 924 pushRequest = 1; 925 } 926 else 927 { 928 Bool managed; 929 char *startCommand; 930 char *proxyAddress; 931 932 if (!GetConfig (configFile, serviceName, &managed, 933 &startCommand, &proxyAddress)) 934 { 935 SendGetProxyAddrReply (requestor, PM_Failure, 936 NULL, "Could not find requested service"); 937 } 938 else 939 { 940 if (managed) 941 { 942 runningProxy = StartNewProxy (serviceName, startCommand); 943 944 if (runningProxy) 945 pushRequest = 1; 946 else 947 { 948 SendGetProxyAddrReply (requestor, PM_Failure, 949 NULL, "Can't start new proxy"); 950 } 951 } 952 else 953 { 954 /* 955 * We have the unmanged proxy's address; now forward 956 * the request to it. 957 */ 958 959 runningProxy = ConnectToProxy (PMOriginatorOpcode, 960 serviceName, proxyAddress); 961 962 if (runningProxy) { 963 SendGetProxyAddr (runningProxy->pmConn, 964 serviceName, serverAddress, 965 hostAddress, startOptions, 966 authLen, authName, authData); 967 pushRequest = 1; 968 } 969 else 970 { 971 /* %%% We should reread the config file and look 972 * for another proxy address before giving up. 973 */ 974 SendGetProxyAddrReply (requestor, PM_Failure, 975 NULL, "Can't connect to proxy"); 976 } 977 } 978 979 if (startCommand) 980 free (startCommand); 981 if (proxyAddress) 982 free (proxyAddress); 983 } 984 } 985 986 if (pushRequest) 987 { 988 PushRequestorQueue (runningProxy, requestor, proxyList, 989 serviceName, serverAddress, hostAddress, startOptions, 990 authLen, authName, authData); 991 } 992} 993 994 995/* ARGSUSED */ 996void 997_XtProcessIceMsgProc(XtPointer client_data, int *source, XtInputId *id) 998{ 999 IceConn ice_conn = (IceConn) client_data; 1000 IceProcessMessagesStatus status; 1001 1002 status = IceProcessMessages (ice_conn, NULL, NULL); 1003 1004 if (status == IceProcessMessagesIOError) 1005 { 1006 Bool activeReqs; 1007 1008 ProxyGone (ice_conn, &activeReqs); 1009 IceSetShutdownNegotiation (ice_conn, False); 1010 IceCloseConnection (ice_conn); 1011 } 1012} 1013 1014 1015void 1016_XtIceWatchProc(IceConn ice_conn, IcePointer client_data, 1017 Bool opening, IcePointer *watch_data) 1018 1019{ 1020 if (opening) 1021 { 1022 XtAppContext appContext = (XtAppContext) client_data; 1023 1024 *watch_data = (IcePointer) XtAppAddInput ( 1025 appContext, 1026 IceConnectionNumber (ice_conn), 1027 (XtPointer) XtInputReadMask, 1028 _XtProcessIceMsgProc, 1029 (XtPointer) ice_conn); 1030 } 1031 else 1032 { 1033 XtRemoveInput ((XtInputId) *watch_data); 1034 } 1035} 1036 1037 1038Status 1039InitWatchProcs(XtAppContext appContext) 1040 1041{ 1042 return (IceAddConnectionWatch (_XtIceWatchProc, (IcePointer) appContext)); 1043} 1044 1045 1046/* 1047 * The real way to handle IO errors is to check the return status 1048 * of IceProcessMessages. xsm properly does this. 1049 * 1050 * Unfortunately, a design flaw exists in the ICE library in which 1051 * a default IO error handler is invoked if no IO error handler is 1052 * installed. This default handler exits. We must avoid this. 1053 * 1054 * To get around this problem, we install an IO error handler that 1055 * does a little magic. Since a previous IO handler might have been 1056 * installed, when we install our IO error handler, we do a little 1057 * trick to get both the previous IO error handler and the default 1058 * IO error handler. When our IO error handler is called, if the 1059 * previous handler is not the default handler, we call it. This 1060 * way, everyone's IO error handler gets called except the stupid 1061 * default one which does an exit! 1062 */ 1063 1064static IceIOErrorHandler prev_handler; 1065 1066void 1067MyIoErrorHandler(IceConn ice_conn) 1068{ 1069 if (prev_handler) 1070 (*prev_handler) (ice_conn); 1071} 1072 1073void 1074InstallIOErrorHandler(void) 1075{ 1076 IceIOErrorHandler default_handler; 1077 1078 prev_handler = IceSetIOErrorHandler (NULL); 1079 default_handler = IceSetIOErrorHandler (MyIoErrorHandler); 1080 if (prev_handler == default_handler) 1081 prev_handler = NULL; 1082} 1083 1084 1085/* 1086 * Since proxy manager does not authenticate connections, we disable 1087 * authentication by always returning true in the host based auth proc. 1088 */ 1089 1090Bool 1091HostBasedAuthProc(char *hostname) 1092{ 1093 return (1); 1094} 1095