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 63const char *PM_VENDOR_STRING = XVENDORNAME; 64const char *PM_VENDOR_RELEASE = XORG_RELEASE; 65 66int verbose = 0; 67 68static XtAppContext appContext; 69 70#define PM_PORT "6500" 71 72static const 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 = 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 = 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 const char *addr, 359 const 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 = 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 = 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 free (serviceName); 543 free (serverAddress); 544 free (hostAddress); 545 free (startOptions); 546 free (authName); 547 free (authData); 548 549 break; 550 } 551 552 case PM_StartProxy: 553 { 554 pmStartProxyMsg *pMsg; 555 char *pData, *pStart; 556 char *serviceName = NULL; 557 char *serverAddress; 558 char *hostAddress; 559 char *startOptions; 560 int authLen; 561 char *authName; 562 char *authData; 563 564#if 0 /* No-op */ 565 CHECK_AT_LEAST_SIZE (iceConn, pmConn->pmOpcode, opcode, 566 length, SIZEOF (pmStartProxyMsg), IceFatalToProtocol); 567#endif 568 569 IceReadCompleteMessage (iceConn, SIZEOF (pmStartProxyMsg), 570 pmStartProxyMsg, pMsg, pStart); 571 572 if (!IceValidIO (iceConn)) 573 { 574 IceDisposeCompleteMessage (iceConn, pStart); 575 return; 576 } 577 578 pData = pStart; 579 580 SKIP_STRING (pData, swap); /* proxy-service */ 581 582 CHECK_COMPLETE_SIZE (iceConn, pmConn->pmOpcode, opcode, 583 length, pData - pStart + SIZEOF (pmStartProxyMsg), 584 pStart, IceFatalToProtocol); 585 586 pData = pStart; 587 588 EXTRACT_STRING (pData, swap, serviceName); 589 590 assert(serviceName); 591 592 if (verbose) 593 printf ("Got StartProxy on fd %d, serviceName = %s\n", 594 IceConnectionNumber(iceConn), serviceName); 595 596 IceDisposeCompleteMessage (iceConn, pStart); 597 598 if (! ActivateProxyService (serviceName, pmConn)) { 599 fputs ("Configuration error: received unexpected StartProxy for service ", stderr); 600 fputs (serviceName, stderr); 601 fputc ('\n', stderr); 602 IceCloseConnection (iceConn); 603 } 604 else { 605 606 /* 607 * Now send the GetProxyAddr message to the proxy. 608 */ 609 if (PeekRequestorQueue(pmConn, 610 NULL, NULL, NULL, 611 &serverAddress, &hostAddress, &startOptions, 612 &authLen, &authName, &authData)) { 613 SendGetProxyAddr(pmConn, 614 serviceName, serverAddress, 615 hostAddress, startOptions, 616 authLen, authName, authData); 617 } 618 else if (verbose) { 619 fputs ("Received StartProxy for service ", stderr); 620 fputs (serviceName, stderr); 621 fputs (" but no waiting GetproxyAddr requests\n", stderr); 622 } 623 } 624 625 free (serviceName); 626 627 break; 628 } 629 630 case PM_GetProxyAddrReply: 631 632 { 633 pmGetProxyAddrReplyMsg *pMsg; 634 char *pData, *pStart; 635 char *addr = NULL, *error = NULL; 636 637#if 0 /* No-op */ 638 CHECK_AT_LEAST_SIZE (iceConn, pmConn->pmOpcode, opcode, 639 length, SIZEOF (pmGetProxyAddrReplyMsg), IceFatalToProtocol); 640#endif 641 642 IceReadCompleteMessage (iceConn, SIZEOF (pmGetProxyAddrReplyMsg), 643 pmGetProxyAddrReplyMsg, pMsg, pStart); 644 645 if (!IceValidIO (iceConn)) 646 { 647 IceDisposeCompleteMessage (iceConn, pStart); 648 return; 649 } 650 651 pData = pStart; 652 653 SKIP_STRING (pData, swap); /* proxy-address */ 654 SKIP_STRING (pData, swap); /* failure-reason */ 655 656 CHECK_COMPLETE_SIZE (iceConn, pmConn->pmOpcode, opcode, 657 length, pData - pStart + SIZEOF (pmGetProxyAddrReplyMsg), 658 pStart, IceFatalToProtocol); 659 660 pData = pStart; 661 662 EXTRACT_STRING (pData, swap, addr); 663 EXTRACT_STRING (pData, swap, error); 664 665 if (verbose) { 666 printf ("Got GetProxyAddrReply from proxy %d, status = %d, ", 667 IceConnectionNumber(iceConn), pMsg->status); 668 if (pMsg->status == PM_Success) 669 printf ("addr = %s\n", addr); 670 else 671 printf ("error = %s\n", error); 672 } 673 674 { /* Ignore any unsolicited replies so we don't get further confused */ 675 running_proxy *proxy = ProxyForPMconn(pmConn); 676 677 if (!proxy || !proxy->requests) 678 { 679 if (verbose) 680 fprintf (stderr, "Received unsolicited GetProxyAddrReply from proxy %d; ignoring it.\n", 681 IceConnectionNumber(iceConn)); 682 683 IceDisposeCompleteMessage (iceConn, pStart); 684 break; 685 } 686 } 687 688 switch (pMsg->status) { 689 690 case PM_Success: 691 { 692 /* 693 * Now send the GetProxyAddr reply to xfindproxy. 694 */ 695 696 SendGetProxyAddrReply ( 697 PopRequestorQueue (pmConn, True, True /* free proxy list */), 698 PM_Success /* status */, addr, NULL); 699 700 break; 701 } 702 703 case PM_Unable: 704 { 705 running_proxy_list *proxyList; 706 char *serviceName, *serverAddress, *hostAddress, *startOptions; 707 PMconn *requestor; 708 int authLen; 709 char *authName; 710 char *authData; 711 712 { 713 running_proxy *proxy = ProxyForPMconn(pmConn); 714 if (proxy) 715 proxy->refused_service = True; 716 else 717 fputs("Internal error: received GetProxyAddrReply from an unknown proxy\n", stderr); 718 } 719 720 if (! PeekRequestorQueue (pmConn, &requestor, 721 &proxyList, &serviceName, &serverAddress, 722 &hostAddress, &startOptions, 723 &authLen, &authName, &authData)) { 724 if (verbose) 725 fputs("Received GetProxyAddrReply from a proxy with no requests\n", stderr); 726 727 proxyList = NULL; 728 serviceName = "?unknown service--internal error"; 729 } 730 731 if (proxyList && (proxyList->current < proxyList->count - 1)) 732 { 733 /* 734 * Ask the next running proxy if it can service this request. 735 */ 736 running_proxy *nextProxy; 737 738 proxyList->current++; 739 nextProxy = proxyList->list[proxyList->current]; 740 741 if (nextProxy->pmConn != NULL) { 742 /* send only if the proxy has started */ 743 SendGetProxyAddr (nextProxy->pmConn, serviceName, 744 serverAddress, hostAddress, startOptions, 745 authLen, authName, authData); 746 } 747 748 PushRequestorQueue (nextProxy, requestor, proxyList, 749 serviceName, serverAddress, hostAddress, startOptions, 750 authLen, authName, authData); 751 752 PopRequestorQueue (pmConn, False, False); 753 } 754 else 755 { 756 /* 757 * Start a new proxy. 758 */ 759 760 running_proxy *runningProxy = NULL; 761 char *startCommand; 762 char *proxyAddress; 763 Bool managed; 764 765 if (!GetConfig (configFile, serviceName, &managed, 766 &startCommand, &proxyAddress)) 767 { 768 SendGetProxyAddrReply (requestor, PM_Failure, 769 NULL, "Could not read proxy manager config file"); 770 } 771 else 772 { 773 runningProxy = StartNewProxy (serviceName, startCommand); 774 775 if (runningProxy) 776 { 777 PushRequestorQueue (runningProxy, 778 requestor, proxyList, 779 serviceName, serverAddress, 780 hostAddress, startOptions, 781 authLen, authName, authData); 782 } 783 else 784 { 785 SendGetProxyAddrReply (pmConn, PM_Failure, 786 NULL, "Can't start new proxy"); 787 } 788 } 789 790 free (startCommand); 791 free (proxyAddress); 792 793 PopRequestorQueue (pmConn, False, 794 runningProxy ? False : True /* free proxy list */); 795 } 796 break; 797 } 798 799 default: 800 if (verbose && pMsg->status != PM_Unable) 801 fprintf(stderr, 802 "Error: proxy returned unrecognized status: %d\n", 803 pMsg->status); 804 /* FALLTHROUGH */ 805 806 case PM_Failure: 807 SendGetProxyAddrReply ( 808 PopRequestorQueue (pmConn, True, True /* free proxy list */), 809 pMsg->status, NULL, error); 810 } 811 812 IceDisposeCompleteMessage (iceConn, pStart); 813 814 /* see if there was more work queued for this proxy */ 815 { 816 char *serviceName, *serverAddress, *hostAddress, *startOptions; 817 int authLen; 818 char *authName, *authData; 819 820 if (PeekRequestorQueue(pmConn, 821 NULL, NULL, &serviceName, 822 &serverAddress, &hostAddress, &startOptions, 823 &authLen, &authName, &authData)) { 824 SendGetProxyAddr(pmConn, 825 serviceName, serverAddress, 826 hostAddress, startOptions, 827 authLen, authName, authData); 828 } 829 } 830 831 free (addr); 832 free (error); 833 834 break; 835 } 836 837 case PM_Error: 838 { 839 iceErrorMsg *pMsg; 840 char *pStart; 841 842 CHECK_AT_LEAST_SIZE (iceConn, pmConn->pmOpcode, PM_Error, length, 843 sizeof(iceErrorMsg), IceFatalToProtocol); 844 845 IceReadCompleteMessage (iceConn, SIZEOF (iceErrorMsg), 846 iceErrorMsg, pMsg, pStart); 847 848 if (!IceValidIO (iceConn)) 849 { 850 IceDisposeCompleteMessage (iceConn, pStart); 851 return; 852 } 853 854 if (swap) 855 { 856 pMsg->errorClass = lswaps (pMsg->errorClass); 857 pMsg->offendingSequenceNum = lswapl (pMsg->offendingSequenceNum); 858 } 859 860 fprintf(stderr, "Received ICE Error: class=0x%x\n offending minor opcode=%d, severity=%d, sequence=%d\n", 861 pMsg->errorClass, pMsg->offendingMinorOpcode, pMsg->severity, 862 (int)pMsg->offendingSequenceNum); 863 864 IceDisposeCompleteMessage (iceConn, pStart); 865 866 break; 867 } 868 869 default: 870 { 871 _IceErrorBadMinor (iceConn, pmConn->pmOpcode, opcode, IceCanContinue); 872 _IceReadSkip (iceConn, length << 3); 873 break; 874 } 875 } 876} 877 878void 879PMSetupProcessMessages(IceConn iceConn, IcePointer clientData, int opcode, 880 unsigned long length, Bool swap, 881 IceReplyWaitInfo *replyWait, Bool *replyReadyRet) 882 883{ 884 assert (replyWait == NULL); 885 886 PMReplyProcessMessages (iceConn, clientData, opcode, length, swap); 887} 888 889 890void 891ForwardRequest(PMconn *requestor, char *serviceName, char *serverAddress, 892 char *hostAddress, char *startOptions, int authLen, 893 char *authName, char *authData) 894{ 895 running_proxy_list *proxyList; 896 running_proxy *runningProxy = NULL; 897 int pushRequest = 0; 898 899 if ((proxyList = GetRunningProxyList ( 900 serviceName, serverAddress)) != NULL) 901 { 902 while (proxyList->current < proxyList->count) { 903 runningProxy = proxyList->list[proxyList->current]; 904 905 if (runningProxy->pmConn != NULL) { 906 SendGetProxyAddr (runningProxy->pmConn, serviceName, 907 serverAddress, hostAddress, NULL, 908 authLen, authName, authData); 909 break; 910 } 911 proxyList->current++; 912 } 913 914 pushRequest = 1; 915 } 916 else 917 { 918 Bool managed; 919 char *startCommand; 920 char *proxyAddress; 921 922 if (!GetConfig (configFile, serviceName, &managed, 923 &startCommand, &proxyAddress)) 924 { 925 SendGetProxyAddrReply (requestor, PM_Failure, 926 NULL, "Could not find requested service"); 927 } 928 else 929 { 930 if (managed) 931 { 932 runningProxy = StartNewProxy (serviceName, startCommand); 933 934 if (runningProxy) 935 pushRequest = 1; 936 else 937 { 938 SendGetProxyAddrReply (requestor, PM_Failure, 939 NULL, "Can't start new proxy"); 940 } 941 } 942 else 943 { 944 /* 945 * We have the unmanged proxy's address; now forward 946 * the request to it. 947 */ 948 949 runningProxy = ConnectToProxy (PMOriginatorOpcode, 950 serviceName, proxyAddress); 951 952 if (runningProxy) { 953 SendGetProxyAddr (runningProxy->pmConn, 954 serviceName, serverAddress, 955 hostAddress, startOptions, 956 authLen, authName, authData); 957 pushRequest = 1; 958 } 959 else 960 { 961 /* %%% We should reread the config file and look 962 * for another proxy address before giving up. 963 */ 964 SendGetProxyAddrReply (requestor, PM_Failure, 965 NULL, "Can't connect to proxy"); 966 } 967 } 968 969 free (startCommand); 970 free (proxyAddress); 971 } 972 } 973 974 if (pushRequest) 975 { 976 PushRequestorQueue (runningProxy, requestor, proxyList, 977 serviceName, serverAddress, hostAddress, startOptions, 978 authLen, authName, authData); 979 } 980} 981 982 983/* ARGSUSED */ 984void 985_XtProcessIceMsgProc(XtPointer client_data, int *source, XtInputId *id) 986{ 987 IceConn ice_conn = (IceConn) client_data; 988 IceProcessMessagesStatus status; 989 990 status = IceProcessMessages (ice_conn, NULL, NULL); 991 992 if (status == IceProcessMessagesIOError) 993 { 994 Bool activeReqs; 995 996 ProxyGone (ice_conn, &activeReqs); 997 IceSetShutdownNegotiation (ice_conn, False); 998 IceCloseConnection (ice_conn); 999 } 1000} 1001 1002 1003void 1004_XtIceWatchProc(IceConn ice_conn, IcePointer client_data, 1005 Bool opening, IcePointer *watch_data) 1006 1007{ 1008 if (opening) 1009 { 1010 XtAppContext appContext = (XtAppContext) client_data; 1011 1012 *watch_data = (IcePointer) XtAppAddInput ( 1013 appContext, 1014 IceConnectionNumber (ice_conn), 1015 (XtPointer) XtInputReadMask, 1016 _XtProcessIceMsgProc, 1017 (XtPointer) ice_conn); 1018 } 1019 else 1020 { 1021 XtRemoveInput ((XtInputId) *watch_data); 1022 } 1023} 1024 1025 1026Status 1027InitWatchProcs(XtAppContext appContext) 1028 1029{ 1030 return (IceAddConnectionWatch (_XtIceWatchProc, (IcePointer) appContext)); 1031} 1032 1033 1034/* 1035 * The real way to handle IO errors is to check the return status 1036 * of IceProcessMessages. xsm properly does this. 1037 * 1038 * Unfortunately, a design flaw exists in the ICE library in which 1039 * a default IO error handler is invoked if no IO error handler is 1040 * installed. This default handler exits. We must avoid this. 1041 * 1042 * To get around this problem, we install an IO error handler that 1043 * does a little magic. Since a previous IO handler might have been 1044 * installed, when we install our IO error handler, we do a little 1045 * trick to get both the previous IO error handler and the default 1046 * IO error handler. When our IO error handler is called, if the 1047 * previous handler is not the default handler, we call it. This 1048 * way, everyone's IO error handler gets called except the stupid 1049 * default one which does an exit! 1050 */ 1051 1052static IceIOErrorHandler prev_handler; 1053 1054void 1055MyIoErrorHandler(IceConn ice_conn) 1056{ 1057 if (prev_handler) 1058 (*prev_handler) (ice_conn); 1059} 1060 1061void 1062InstallIOErrorHandler(void) 1063{ 1064 IceIOErrorHandler default_handler; 1065 1066 prev_handler = IceSetIOErrorHandler (NULL); 1067 default_handler = IceSetIOErrorHandler (MyIoErrorHandler); 1068 if (prev_handler == default_handler) 1069 prev_handler = NULL; 1070} 1071 1072 1073/* 1074 * Since proxy manager does not authenticate connections, we disable 1075 * authentication by always returning true in the host based auth proc. 1076 */ 1077 1078Bool 1079HostBasedAuthProc(char *hostname) 1080{ 1081 return (1); 1082} 1083