main.c revision b3078add
15c10afb9Smrg
25c10afb9Smrg/*
35c10afb9SmrgCopyright 1996, 1998  The Open Group
45c10afb9Smrg
55c10afb9SmrgPermission to use, copy, modify, distribute, and sell this software and its
65c10afb9Smrgdocumentation for any purpose is hereby granted without fee, provided that
75c10afb9Smrgthe above copyright notice appear in all copies and that both that
85c10afb9Smrgcopyright notice and this permission notice appear in supporting
95c10afb9Smrgdocumentation.
105c10afb9Smrg
115c10afb9SmrgThe above copyright notice and this permission notice shall be included
125c10afb9Smrgin all copies or substantial portions of the Software.
135c10afb9Smrg
145c10afb9SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
155c10afb9SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
165c10afb9SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
175c10afb9SmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
185c10afb9SmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
195c10afb9SmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
205c10afb9SmrgOTHER DEALINGS IN THE SOFTWARE.
215c10afb9Smrg
225c10afb9SmrgExcept as contained in this notice, the name of The Open Group shall
235c10afb9Smrgnot be used in advertising or otherwise to promote the sale, use or
245c10afb9Smrgother dealings in this Software without prior written authorization
255c10afb9Smrgfrom The Open Group.
265c10afb9Smrg*/
275c10afb9Smrg
285c10afb9Smrg#include <stdlib.h>
295c10afb9Smrg#include "pmint.h"
305c10afb9Smrg#include <X11/StringDefs.h>
315c10afb9Smrg#include <X11/Intrinsic.h>
325c10afb9Smrg#include <X11/ICE/ICEmsg.h>
335c10afb9Smrg#include <X11/ICE/ICEproto.h>
345c10afb9Smrg#include <X11/PM/PMproto.h>
355c10afb9Smrg#include <X11/PM/PM.h>
365c10afb9Smrg#include "pmdb.h"
375c10afb9Smrg#include "config.h"
385c10afb9Smrg#include <assert.h>
395c10afb9Smrg
405c10afb9Smrg#include <netinet/in.h>
415c10afb9Smrg#include <arpa/inet.h>
425c10afb9Smrg#include <sys/socket.h>
435c10afb9Smrg#include <netdb.h>
445c10afb9Smrg
455c10afb9Smrgstatic int PMprotocolSetupProc ( IceConn iceConn, int majorVersion,
465c10afb9Smrg				 int minorVersion, char *vendor,
475c10afb9Smrg				 char *release, IcePointer *clientDataRet,
485c10afb9Smrg				 char **failureReasonRet );
495c10afb9Smrgstatic void SendGetProxyAddr ( PMconn *pmConn, char *serviceName,
505c10afb9Smrg			       char *serverAddress, char *hostAddress,
515c10afb9Smrg			       char *startOptions, int authLen,
525c10afb9Smrg			       char *authName, char *authData );
535c10afb9Smrg
545c10afb9Smrgstatic int PMAcceptorOpcode;
555c10afb9Smrgstatic int PMOriginatorOpcode;
565c10afb9Smrg
57b3078addSmrgstatic int PMversionCount = 1;
58b3078addSmrgstatic IcePaVersionRec	PMReplyVersions[] = {{PM_MAJOR_VERSION, PM_MINOR_VERSION,
595c10afb9Smrg				      PMReplyProcessMessages}};
60b3078addSmrgstatic IcePoVersionRec	PMSetupVersions[] = {{PM_MAJOR_VERSION, PM_MINOR_VERSION,
615c10afb9Smrg				      PMSetupProcessMessages}};
625c10afb9Smrg
635c10afb9Smrgchar *PM_VENDOR_STRING = XVENDORNAME;
645c10afb9Smrgchar *PM_VENDOR_RELEASE = XORG_RELEASE;
655c10afb9Smrg
665c10afb9Smrgint verbose = 0;
675c10afb9Smrg
68b3078addSmrgstatic XtAppContext	appContext;
695c10afb9Smrg
705c10afb9Smrg#define PM_PORT "6500"
715c10afb9Smrg
72b3078addSmrgstatic char *configFile = NULL;
735c10afb9Smrg
745c10afb9Smrgvoid
75b3078addSmrgUsage(void)
765c10afb9Smrg{
775c10afb9Smrg    fprintf (stderr, "Usage: proxymngr [-config file] [-verbose]\n");
785c10afb9Smrg    exit (1);
795c10afb9Smrg}
805c10afb9Smrg
815c10afb9Smrgvoid
82b3078addSmrgSetCloseOnExec(int fd)
835c10afb9Smrg{
845c10afb9Smrg#ifdef F_SETFD
855c10afb9Smrg#ifdef FD_CLOEXEC
865c10afb9Smrg    (void) fcntl (fd, F_SETFD, FD_CLOEXEC);
875c10afb9Smrg#else
885c10afb9Smrg    (void) fcntl (fd, F_SETFD, 1);
895c10afb9Smrg#endif /* FD_CLOEXEC */
905c10afb9Smrg#endif /* F_SETFD */
915c10afb9Smrg}
925c10afb9Smrg
935c10afb9Smrg/*
945c10afb9Smrg * Main program
955c10afb9Smrg */
965c10afb9Smrg
975c10afb9Smrgint
985c10afb9Smrgmain (int argc, char *argv[])
995c10afb9Smrg{
1005c10afb9Smrg    IceListenObj *listenObjs;
1015c10afb9Smrg    int		numTransports, i;
1025c10afb9Smrg    char	errormsg[256];
1035c10afb9Smrg    char	*networkIds, *p;
1045c10afb9Smrg
1055c10afb9Smrg    for (i = 1; i < argc; i++)
1065c10afb9Smrg    {
1075c10afb9Smrg	if (strcmp (argv[i], "-config") == 0)
1085c10afb9Smrg	{
1095c10afb9Smrg	    if (++i < argc)
1105c10afb9Smrg	        configFile = argv[i];
1115c10afb9Smrg	    else
1125c10afb9Smrg		Usage ();
1135c10afb9Smrg	}
1145c10afb9Smrg	else if (strcmp(argv[i], "-verbose") == 0)
1155c10afb9Smrg	{
1165c10afb9Smrg	    verbose = 1;
1175c10afb9Smrg	}
1185c10afb9Smrg	else
1195c10afb9Smrg	    Usage ();
1205c10afb9Smrg    }
1215c10afb9Smrg
1225c10afb9Smrg    if (!configFile)
1235c10afb9Smrg	configFile = CONFIG_FILE;
1245c10afb9Smrg
1255c10afb9Smrg    if (verbose)
1265c10afb9Smrg	fprintf (stderr, "config file = %s\n", configFile);
1275c10afb9Smrg
1285c10afb9Smrg    /*
1295c10afb9Smrg     * Install an IO error handler.
1305c10afb9Smrg     */
1315c10afb9Smrg    InstallIOErrorHandler ();
1325c10afb9Smrg
1335c10afb9Smrg    /*
1345c10afb9Smrg     * Register support for PROXY_MANAGEMENT.
1355c10afb9Smrg     */
1365c10afb9Smrg
1375c10afb9Smrg    /* For Managed proxies, the proxy does the Setup */
1385c10afb9Smrg    if ((PMAcceptorOpcode = IceRegisterForProtocolReply (
1395c10afb9Smrg	PM_PROTOCOL_NAME, PM_VENDOR_STRING, PM_VENDOR_RELEASE,
1405c10afb9Smrg	PMversionCount, PMReplyVersions,
1415c10afb9Smrg	0, /* authcount */
1425c10afb9Smrg	NULL, /* authnames */
1435c10afb9Smrg        NULL, /* authprocs */
1445c10afb9Smrg        HostBasedAuthProc,
1455c10afb9Smrg	PMprotocolSetupProc,
1465c10afb9Smrg	NULL, /* protocolActivateProc */
1475c10afb9Smrg	NULL  /* IceIOErrorProc */ )) < 0)
1485c10afb9Smrg    {
1495c10afb9Smrg	fprintf (stderr,
1505c10afb9Smrg	    "Could not register PROXY_MANAGEMENT protocol reply with ICE");
1515c10afb9Smrg	exit (1);
1525c10afb9Smrg    }
1535c10afb9Smrg
1545c10afb9Smrg    /* For Unmanaged proxies, we do the Setup
1555c10afb9Smrg     * ICElib doesn't specify that the same opCode will be returned
1565c10afb9Smrg     * so don't bet on it.
1575c10afb9Smrg     */
1585c10afb9Smrg    if ((PMOriginatorOpcode = IceRegisterForProtocolSetup (
1595c10afb9Smrg	PM_PROTOCOL_NAME, PM_VENDOR_STRING, PM_VENDOR_RELEASE,
1605c10afb9Smrg	PMversionCount, PMSetupVersions,
1615c10afb9Smrg	0, /* authcount */
1625c10afb9Smrg	NULL, /* authnames */
1635c10afb9Smrg        NULL, /* authprocs */
1645c10afb9Smrg	NULL  /* IceIOErrorProc */ )) < 0)
1655c10afb9Smrg    {
1665c10afb9Smrg	fprintf (stderr,
1675c10afb9Smrg	    "Could not register PROXY_MANAGEMENT protocol setup with ICE");
1685c10afb9Smrg	exit (1);
1695c10afb9Smrg    }
1705c10afb9Smrg
1715c10afb9Smrg
1725c10afb9Smrg    if (!IceListenForWellKnownConnections (
1735c10afb9Smrg	PM_PORT, &numTransports, &listenObjs, 256, errormsg))
1745c10afb9Smrg    {
1755c10afb9Smrg	fprintf (stderr, "%s\n", errormsg);
1765c10afb9Smrg	exit (1);
1775c10afb9Smrg    }
1785c10afb9Smrg
1795c10afb9Smrg    networkIds = IceComposeNetworkIdList (numTransports, listenObjs);
1805c10afb9Smrg    p = (char *) malloc(sizeof ("PROXY_MANAGER") + strlen(networkIds) + 2);
1815c10afb9Smrg    sprintf (p, "PROXY_MANAGER=%s", networkIds);
1825c10afb9Smrg    putenv (p);
1835c10afb9Smrg    printf ("%s\n", p);
1845c10afb9Smrg    free (networkIds);
1855c10afb9Smrg
1865c10afb9Smrg    appContext = XtCreateApplicationContext ();
1875c10afb9Smrg
1885c10afb9Smrg    InitWatchProcs (appContext);
1895c10afb9Smrg
1905c10afb9Smrg    for (i = 0; i < numTransports; i++)
1915c10afb9Smrg    {
1925c10afb9Smrg	XtAppAddInput (appContext,
1935c10afb9Smrg	    IceGetListenConnectionNumber (listenObjs[i]),
1945c10afb9Smrg	    (XtPointer) XtInputReadMask,
1955c10afb9Smrg	    NewConnectionXtProc, (XtPointer) listenObjs[i]);
1965c10afb9Smrg
1975c10afb9Smrg	IceSetHostBasedAuthProc (listenObjs[i], HostBasedAuthProc);
1985c10afb9Smrg
1995c10afb9Smrg        SetCloseOnExec (IceGetListenConnectionNumber (listenObjs[i]));
2005c10afb9Smrg    }
2015c10afb9Smrg
2025c10afb9Smrg    /*
2035c10afb9Smrg     * Main loop
2045c10afb9Smrg     */
2055c10afb9Smrg    XtAppMainLoop (appContext);
2065c10afb9Smrg    exit (0);
2075c10afb9Smrg}
2085c10afb9Smrg
2095c10afb9Smrg
2105c10afb9Smrg/*
2115c10afb9Smrg * Xt callback invoked when a client attempts to connect.
2125c10afb9Smrg */
2135c10afb9Smrg
2145c10afb9Smrg/* ARGSUSED */
2155c10afb9Smrgvoid
216b3078addSmrgNewConnectionXtProc(XtPointer client_data, int *source, XtInputId *id)
2175c10afb9Smrg{
2185c10afb9Smrg    IceConn 	ice_conn;
2195c10afb9Smrg    char	*connstr;
2205c10afb9Smrg    IceAcceptStatus status;
2215c10afb9Smrg
2225c10afb9Smrg    ice_conn = IceAcceptConnection((IceListenObj) client_data, &status);
2235c10afb9Smrg    if (! ice_conn) {
2245c10afb9Smrg	if (verbose)
2255c10afb9Smrg	    printf ("IceAcceptConnection failed\n");
2265c10afb9Smrg    } else {
2275c10afb9Smrg	IceConnectStatus cstatus;
2285c10afb9Smrg
2295c10afb9Smrg        /*
2305c10afb9Smrg	 * Mark this fd to be closed upon exec
2315c10afb9Smrg	 */
2325c10afb9Smrg        SetCloseOnExec (IceConnectionNumber (ice_conn));
2335c10afb9Smrg
2345c10afb9Smrg	while ((cstatus = IceConnectionStatus (ice_conn))==IceConnectPending) {
2355c10afb9Smrg	    XtAppProcessEvent (appContext, XtIMAll);
2365c10afb9Smrg	}
2375c10afb9Smrg
2385c10afb9Smrg	if (cstatus == IceConnectAccepted) {
2395c10afb9Smrg	    if (verbose) {
2405c10afb9Smrg		printf ("ICE Connection opened by client, IceConn fd = %d, ",
2415c10afb9Smrg			IceConnectionNumber (ice_conn));
2425c10afb9Smrg		connstr = IceConnectionString (ice_conn);
2435c10afb9Smrg		printf ("Accept at networkId %s\n", connstr);
2445c10afb9Smrg		free (connstr);
2455c10afb9Smrg		printf ("\n");
2465c10afb9Smrg	    }
2475c10afb9Smrg	} else {
2485c10afb9Smrg	    if (verbose)
2495c10afb9Smrg	    {
2505c10afb9Smrg		if (cstatus == IceConnectIOError)
2515c10afb9Smrg		    printf ("IO error opening ICE Connection!\n");
2525c10afb9Smrg		else
2535c10afb9Smrg		    printf ("ICE Connection rejected!\n");
2545c10afb9Smrg	    }
2555c10afb9Smrg
2565c10afb9Smrg	    IceCloseConnection (ice_conn);
2575c10afb9Smrg	}
2585c10afb9Smrg    }
2595c10afb9Smrg}
2605c10afb9Smrg
2615c10afb9Smrg
2625c10afb9Smrg/*
2635c10afb9Smrg * See ConnectToProxy() if you change any of the pmConn structure
2645c10afb9Smrg */
2655c10afb9Smrgstatic Status
266b3078addSmrgPMprotocolSetupProc(IceConn iceConn, int majorVersion, int minorVersion,
267b3078addSmrg		    char *vendor, char *release, IcePointer *clientDataRet,
268b3078addSmrg		    char **failureReasonRet)
2695c10afb9Smrg
2705c10afb9Smrg{
2715c10afb9Smrg    /*
2725c10afb9Smrg     * Allocate new pmConn.
2735c10afb9Smrg     */
2745c10afb9Smrg
2755c10afb9Smrg    static char standardError[] = "Could not allocate memory for new client";
2765c10afb9Smrg    PMconn *pmConn;
2775c10afb9Smrg
2785c10afb9Smrg    if ((pmConn = (PMconn *) malloc (sizeof (PMconn))) == NULL)
2795c10afb9Smrg    {
2805c10afb9Smrg	if (verbose)
2815c10afb9Smrg	    fprintf (stderr, "%s\n", standardError);
2825c10afb9Smrg
2835c10afb9Smrg	*failureReasonRet = standardError;
2845c10afb9Smrg	return (0);
2855c10afb9Smrg    }
2865c10afb9Smrg
2875c10afb9Smrg    pmConn->iceConn = iceConn;
2885c10afb9Smrg    pmConn->pmOpcode = PMAcceptorOpcode;
2895c10afb9Smrg    pmConn->proto_major_version = majorVersion;
2905c10afb9Smrg    pmConn->proto_minor_version = minorVersion;
2915c10afb9Smrg    pmConn->vendor = vendor;
2925c10afb9Smrg    pmConn->release = release;
2935c10afb9Smrg
2945c10afb9Smrg    *clientDataRet = (IcePointer) pmConn;
2955c10afb9Smrg
2965c10afb9Smrg    return (1);
2975c10afb9Smrg}
2985c10afb9Smrg
2995c10afb9Smrg
3005c10afb9Smrgstatic void
3015c10afb9SmrgSendGetProxyAddr (
3025c10afb9Smrg    PMconn *pmConn,
3035c10afb9Smrg    char *serviceName,
3045c10afb9Smrg    char *serverAddress,
3055c10afb9Smrg    char *hostAddress,
3065c10afb9Smrg    char *startOptions,
3075c10afb9Smrg    int authLen,
3085c10afb9Smrg    char *authName,
3095c10afb9Smrg    char *authData)
3105c10afb9Smrg
3115c10afb9Smrg{
3125c10afb9Smrg    IceConn iceConn = pmConn->iceConn;
3135c10afb9Smrg    pmGetProxyAddrMsg *pMsg;
3145c10afb9Smrg    char *pData;
3155c10afb9Smrg    int len;
3165c10afb9Smrg
3175c10afb9Smrg    if (verbose) {
3185c10afb9Smrg	printf ("Sending GetProxyAddr to proxy %d, serviceName = %s, serverAddr = %s\n",
3195c10afb9Smrg		IceConnectionNumber(iceConn), serviceName, serverAddress);
3205c10afb9Smrg	printf ("  hostAddr = %s, options = %s, authLen = %d\n",
3215c10afb9Smrg		hostAddress ? hostAddress : "",
3225c10afb9Smrg		startOptions ? startOptions : "",
3235c10afb9Smrg		authLen);
3245c10afb9Smrg	if (authLen > 0)
3255c10afb9Smrg	    printf ("  authName = %s\n", authName);
3265c10afb9Smrg    }
3275c10afb9Smrg
3285c10afb9Smrg    len = STRING_BYTES (serviceName) +
3295c10afb9Smrg	  STRING_BYTES (serverAddress) +
3305c10afb9Smrg	  STRING_BYTES (hostAddress) +
3315c10afb9Smrg	  STRING_BYTES (startOptions) +
3325c10afb9Smrg	  (authLen > 0 ? (STRING_BYTES (authName) + authLen) : 0);
3335c10afb9Smrg
3345c10afb9Smrg    IceGetHeaderExtra (iceConn, pmConn->pmOpcode, PM_GetProxyAddr,
3355c10afb9Smrg	  SIZEOF (pmGetProxyAddrMsg), WORD64COUNT (len),
3365c10afb9Smrg	  pmGetProxyAddrMsg, pMsg, pData);
3375c10afb9Smrg
3385c10afb9Smrg    pMsg->authLen = authLen;
3395c10afb9Smrg
3405c10afb9Smrg    STORE_STRING (pData, serviceName);
3415c10afb9Smrg    STORE_STRING (pData, serverAddress);
3425c10afb9Smrg    STORE_STRING (pData, hostAddress);
3435c10afb9Smrg    STORE_STRING (pData, startOptions);
3445c10afb9Smrg    if (authLen > 0)
3455c10afb9Smrg    {
3465c10afb9Smrg	STORE_STRING (pData, authName);
3475c10afb9Smrg	memcpy (pData, authData, authLen);
3485c10afb9Smrg    }
3495c10afb9Smrg
3505c10afb9Smrg    IceFlush (iceConn);
3515c10afb9Smrg}
3525c10afb9Smrg
3535c10afb9Smrg
3545c10afb9Smrgvoid
3555c10afb9SmrgSendGetProxyAddrReply (
3565c10afb9Smrg    PMconn *requestor,
3575c10afb9Smrg    int status,
3585c10afb9Smrg    char *addr,
3595c10afb9Smrg    char *error)
3605c10afb9Smrg
3615c10afb9Smrg{
3625c10afb9Smrg    int len = STRING_BYTES (addr) + STRING_BYTES (error);
3635c10afb9Smrg    pmGetProxyAddrReplyMsg *pReply;
3645c10afb9Smrg    char *pData;
3655c10afb9Smrg
3665c10afb9Smrg    if (verbose) {
3675c10afb9Smrg	fputs ("Replying with ", stderr);
3685c10afb9Smrg	fputs (status == PM_Success ? "Success: " :
3695c10afb9Smrg	       status == PM_Failure ? "Failure: " :
3705c10afb9Smrg	       status == PM_Unable  ? "Unable: "  :
3715c10afb9Smrg	       "?unknown status", stderr);
3725c10afb9Smrg	fputs (status == PM_Success ? addr : error, stderr);
3735c10afb9Smrg	fputc ('\n', stderr);
3745c10afb9Smrg    }
3755c10afb9Smrg
3765c10afb9Smrg    IceGetHeaderExtra (requestor->iceConn,
3775c10afb9Smrg	requestor->pmOpcode, PM_GetProxyAddrReply,
3785c10afb9Smrg	SIZEOF (pmGetProxyAddrReplyMsg), WORD64COUNT (len),
3795c10afb9Smrg	pmGetProxyAddrReplyMsg, pReply, pData);
3805c10afb9Smrg
3815c10afb9Smrg    pReply->status = status;
3825c10afb9Smrg
3835c10afb9Smrg    STORE_STRING (pData, addr);
3845c10afb9Smrg    STORE_STRING (pData, error);
3855c10afb9Smrg
3865c10afb9Smrg    IceFlush (requestor->iceConn);
3875c10afb9Smrg}
3885c10afb9Smrg
3895c10afb9Smrg
3905c10afb9Smrg
3915c10afb9Smrgvoid
392b3078addSmrgPMReplyProcessMessages(IceConn iceConn, IcePointer clientData, int opcode,
393b3078addSmrg		       unsigned long length, Bool swap)
3945c10afb9Smrg
3955c10afb9Smrg{
3965c10afb9Smrg    PMconn *pmConn = (PMconn *) clientData;
3975c10afb9Smrg
3985c10afb9Smrg    assert(pmConn->iceConn == iceConn);
3995c10afb9Smrg
4005c10afb9Smrg    switch (opcode)
4015c10afb9Smrg    {
4025c10afb9Smrg    case PM_GetProxyAddr:
4035c10afb9Smrg    {
4045c10afb9Smrg	pmGetProxyAddrMsg 	*pMsg;
4055c10afb9Smrg	char 			*pData, *pStart;
4065c10afb9Smrg	char			*serviceName = NULL, *serverAddress = NULL;
4075c10afb9Smrg	char			*hostAddress = NULL, *startOptions = NULL;
4085c10afb9Smrg	char			*authName = NULL, *authData = NULL;
4095c10afb9Smrg	int			authLen;
4105c10afb9Smrg
4115c10afb9Smrg#if 0 /* No-op */
4125c10afb9Smrg	CHECK_AT_LEAST_SIZE (iceConn, pmConn->pmOpcode, opcode,
4135c10afb9Smrg	    length, SIZEOF (pmGetProxyAddrMsg), IceFatalToProtocol);
4145c10afb9Smrg#endif
4155c10afb9Smrg
4165c10afb9Smrg	IceReadCompleteMessage (iceConn, SIZEOF (pmGetProxyAddrMsg),
4175c10afb9Smrg	    pmGetProxyAddrMsg, pMsg, pStart);
4185c10afb9Smrg
4195c10afb9Smrg	if (!IceValidIO (iceConn))
4205c10afb9Smrg	{
4215c10afb9Smrg	    IceDisposeCompleteMessage (iceConn, pStart);
4225c10afb9Smrg	    return;
4235c10afb9Smrg	}
4245c10afb9Smrg
4255c10afb9Smrg	authLen = swap ? lswaps (pMsg->authLen) : pMsg->authLen;
4265c10afb9Smrg
4275c10afb9Smrg	pData = pStart;
4285c10afb9Smrg
4295c10afb9Smrg	SKIP_STRING (pData, swap);	/* proxy-service */
4305c10afb9Smrg	SKIP_STRING (pData, swap);	/* server-address */
4315c10afb9Smrg	SKIP_STRING (pData, swap);	/* host-address */
4325c10afb9Smrg	SKIP_STRING (pData, swap);	/* start-options */
4335c10afb9Smrg	if (authLen > 0)
4345c10afb9Smrg	{
4355c10afb9Smrg	    SKIP_STRING (pData, swap);		    /* auth-name */
4365c10afb9Smrg	    pData += (authLen +  PAD64 (authLen));  /* auth-data */
4375c10afb9Smrg	}
4385c10afb9Smrg
4395c10afb9Smrg	CHECK_COMPLETE_SIZE (iceConn, pmConn->pmOpcode, opcode,
4405c10afb9Smrg	   length, pData - pStart + SIZEOF (pmGetProxyAddrMsg),
4415c10afb9Smrg	   pStart, IceFatalToProtocol);
4425c10afb9Smrg
4435c10afb9Smrg	pData = pStart;
4445c10afb9Smrg
4455c10afb9Smrg	EXTRACT_STRING (pData, swap, serviceName);
4465c10afb9Smrg	EXTRACT_STRING (pData, swap, serverAddress);
4475c10afb9Smrg	EXTRACT_STRING (pData, swap, hostAddress);
4485c10afb9Smrg	EXTRACT_STRING (pData, swap, startOptions);
4495c10afb9Smrg	if (authLen > 0)
4505c10afb9Smrg	{
4515c10afb9Smrg	    EXTRACT_STRING (pData, swap, authName);
4525c10afb9Smrg	    authData = (char *) malloc (authLen);
4535c10afb9Smrg	    memcpy (authData, pData, authLen);
4545c10afb9Smrg	}
4555c10afb9Smrg
4565c10afb9Smrg	if (serverAddress)
4575c10afb9Smrg	{
4585c10afb9Smrg	    /*
4595c10afb9Smrg	     * Assume that if serverAddress is something like :0 or :0.0
4605c10afb9Smrg	     * then the request is for a server on the client's host.
4615c10afb9Smrg	     *
4625c10afb9Smrg	     * However, the proxy handling this request may be on a
4635c10afb9Smrg	     * different host than the client or the client host,
4645c10afb9Smrg	     * proxy host and the server host may all be different,
4655c10afb9Smrg	     * thus a serverAddress of :0 or :0.0 is not useful.
4665c10afb9Smrg	     * Therefore, change serverAddress to use the client's
4675c10afb9Smrg	     * hostname.
4685c10afb9Smrg	     */
4695c10afb9Smrg	    char		*tmpName;
4705c10afb9Smrg
4715c10afb9Smrg	    tmpName = strrchr (serverAddress, ':');
4725c10afb9Smrg
4735c10afb9Smrg	    if (tmpName && ((tmpName == serverAddress) ||
4745c10afb9Smrg			    (!strncmp (serverAddress, "unix:", 5))))
4755c10afb9Smrg	    {
4765c10afb9Smrg#if defined(IPv6) && defined(AF_INET6)
4775c10afb9Smrg		struct sockaddr_storage	serverSock;
4785c10afb9Smrg#else
4795c10afb9Smrg		struct sockaddr_in	serverSock;
4805c10afb9Smrg#endif
4815c10afb9Smrg		int 			retVal;
4825c10afb9Smrg		int 			addrLen = sizeof(serverSock);
4835c10afb9Smrg
4845c10afb9Smrg		retVal = getpeername(IceConnectionNumber(iceConn),
4855c10afb9Smrg				     (struct sockaddr *) &serverSock,
4865c10afb9Smrg				     (void *) &addrLen);
4875c10afb9Smrg		if (!retVal)
4885c10afb9Smrg		{
4895c10afb9Smrg		    char *canonname = NULL;
4905c10afb9Smrg#if defined(IPv6) && defined(AF_INET6)
4915c10afb9Smrg		    char hostname[NI_MAXHOST];
4925c10afb9Smrg		    struct addrinfo *ai = NULL, hints;
4935c10afb9Smrg
4945c10afb9Smrg		    if (getnameinfo((struct sockaddr *) &serverSock,
4955c10afb9Smrg		      addrLen, hostname, sizeof(hostname), NULL, 0, 0) == 0) {
4965c10afb9Smrg			(void)memset(&hints, 0, sizeof(hints));
4975c10afb9Smrg			hints.ai_flags = AI_CANONNAME;
4985c10afb9Smrg			if (getaddrinfo(hostname, NULL, &hints, &ai) == 0) {
4995c10afb9Smrg			    canonname = ai->ai_canonname;
5005c10afb9Smrg			}
5015c10afb9Smrg		    }
5025c10afb9Smrg#else
5035c10afb9Smrg		    struct hostent *hostent;
5045c10afb9Smrg
5055c10afb9Smrg		    hostent = gethostbyname (inet_ntoa(serverSock.sin_addr));
5065c10afb9Smrg
5075c10afb9Smrg		    if (hostent && hostent->h_name)
5085c10afb9Smrg			canonname = hostent->h_name;
5095c10afb9Smrg#endif
5105c10afb9Smrg		    if (canonname)
5115c10afb9Smrg		    {
5125c10afb9Smrg			int		len;
5135c10afb9Smrg			char		* pch = strdup (tmpName);
5145c10afb9Smrg
5155c10afb9Smrg			len = strlen(canonname) + strlen(tmpName) + 1;
5165c10afb9Smrg			serverAddress = (char *) realloc (serverAddress, len);
5175c10afb9Smrg			sprintf (serverAddress, "%s%s", canonname, pch);
5185c10afb9Smrg			free (pch);
5195c10afb9Smrg		    }
5205c10afb9Smrg#if defined(IPv6) && defined(AF_INET6)
5215c10afb9Smrg		    if (ai != NULL)
5225c10afb9Smrg			freeaddrinfo(ai);
5235c10afb9Smrg#endif
5245c10afb9Smrg		}
5255c10afb9Smrg	    }
5265c10afb9Smrg	}
5275c10afb9Smrg
5285c10afb9Smrg	if (verbose) {
5295c10afb9Smrg	    printf ("Got GetProxyAddr, serviceName = %s, serverAddr = %s\n",
5305c10afb9Smrg		    serviceName, serverAddress);
5315c10afb9Smrg	    printf ("  hostAddr = %s, options = %s, authLen = %d\n",
5325c10afb9Smrg		    hostAddress, startOptions, authLen);
5335c10afb9Smrg	    if (authLen > 0)
5345c10afb9Smrg		printf ("  authName = %s\n", authName);
5355c10afb9Smrg	}
5365c10afb9Smrg
5375c10afb9Smrg	IceDisposeCompleteMessage (iceConn, pStart);
5385c10afb9Smrg
5395c10afb9Smrg	ForwardRequest (pmConn, serviceName, serverAddress, hostAddress,
5405c10afb9Smrg			startOptions, authLen, authName, authData);
5415c10afb9Smrg
5425c10afb9Smrg	if (serviceName)
5435c10afb9Smrg	    free (serviceName);
5445c10afb9Smrg	if (serverAddress)
5455c10afb9Smrg	    free (serverAddress);
5465c10afb9Smrg	if (hostAddress)
5475c10afb9Smrg	    free (hostAddress);
5485c10afb9Smrg	if (startOptions)
5495c10afb9Smrg	    free (startOptions);
5505c10afb9Smrg	if (authName)
5515c10afb9Smrg	    free (authName);
5525c10afb9Smrg	if (authData)
5535c10afb9Smrg	    free (authData);
5545c10afb9Smrg
5555c10afb9Smrg	break;
5565c10afb9Smrg    }
5575c10afb9Smrg
5585c10afb9Smrg    case PM_StartProxy:
5595c10afb9Smrg    {
5605c10afb9Smrg	pmStartProxyMsg *pMsg;
5615c10afb9Smrg	char 		*pData, *pStart;
5625c10afb9Smrg	char		*serviceName = NULL;
5635c10afb9Smrg	char		*serverAddress;
5645c10afb9Smrg	char		*hostAddress;
5655c10afb9Smrg	char		*startOptions;
5665c10afb9Smrg	int		authLen;
5675c10afb9Smrg	char		*authName;
5685c10afb9Smrg	char		*authData;
5695c10afb9Smrg
5705c10afb9Smrg#if 0 /* No-op */
5715c10afb9Smrg	CHECK_AT_LEAST_SIZE (iceConn, pmConn->pmOpcode, opcode,
5725c10afb9Smrg	    length, SIZEOF (pmStartProxyMsg), IceFatalToProtocol);
5735c10afb9Smrg#endif
5745c10afb9Smrg
5755c10afb9Smrg	IceReadCompleteMessage (iceConn, SIZEOF (pmStartProxyMsg),
5765c10afb9Smrg	    pmStartProxyMsg, pMsg, pStart);
5775c10afb9Smrg
5785c10afb9Smrg	if (!IceValidIO (iceConn))
5795c10afb9Smrg	{
5805c10afb9Smrg	    IceDisposeCompleteMessage (iceConn, pStart);
5815c10afb9Smrg	    return;
5825c10afb9Smrg	}
5835c10afb9Smrg
5845c10afb9Smrg	pData = pStart;
5855c10afb9Smrg
5865c10afb9Smrg	SKIP_STRING (pData, swap);	/* proxy-service */
5875c10afb9Smrg
5885c10afb9Smrg	CHECK_COMPLETE_SIZE (iceConn, pmConn->pmOpcode, opcode,
5895c10afb9Smrg	   length, pData - pStart + SIZEOF (pmStartProxyMsg),
5905c10afb9Smrg	   pStart, IceFatalToProtocol);
5915c10afb9Smrg
5925c10afb9Smrg	pData = pStart;
5935c10afb9Smrg
5945c10afb9Smrg	EXTRACT_STRING (pData, swap, serviceName);
5955c10afb9Smrg
5965c10afb9Smrg	assert(serviceName);
5975c10afb9Smrg
5985c10afb9Smrg	if (verbose)
5995c10afb9Smrg	    printf ("Got StartProxy on fd %d, serviceName = %s\n",
6005c10afb9Smrg		    IceConnectionNumber(iceConn), serviceName);
6015c10afb9Smrg
6025c10afb9Smrg	IceDisposeCompleteMessage (iceConn, pStart);
6035c10afb9Smrg
6045c10afb9Smrg	if (! ActivateProxyService (serviceName, pmConn)) {
6055c10afb9Smrg	    fputs ("Configuration error: received unexpected StartProxy for service ", stderr);
6065c10afb9Smrg	    fputs (serviceName, stderr);
6075c10afb9Smrg	    fputc ('\n', stderr);
6085c10afb9Smrg	    IceCloseConnection (iceConn);
6095c10afb9Smrg	}
6105c10afb9Smrg	else {
6115c10afb9Smrg
6125c10afb9Smrg	    /*
6135c10afb9Smrg	     * Now send the GetProxyAddr message to the proxy.
6145c10afb9Smrg	     */
6155c10afb9Smrg	    if (PeekRequestorQueue(pmConn,
6165c10afb9Smrg				   NULL, NULL, NULL,
6175c10afb9Smrg				   &serverAddress, &hostAddress, &startOptions,
6185c10afb9Smrg				   &authLen, &authName, &authData)) {
6195c10afb9Smrg		SendGetProxyAddr(pmConn,
6205c10afb9Smrg				 serviceName, serverAddress,
6215c10afb9Smrg				 hostAddress, startOptions,
6225c10afb9Smrg				 authLen, authName, authData);
6235c10afb9Smrg	    }
6245c10afb9Smrg	    else if (verbose) {
6255c10afb9Smrg		    fputs ("Received StartProxy for service ", stderr);
6265c10afb9Smrg		    fputs (serviceName, stderr);
6275c10afb9Smrg		    fputs (" but no waiting GetproxyAddr requests\n", stderr);
6285c10afb9Smrg	    }
6295c10afb9Smrg	}
6305c10afb9Smrg
6315c10afb9Smrg	free (serviceName);
6325c10afb9Smrg
6335c10afb9Smrg	break;
6345c10afb9Smrg    }
6355c10afb9Smrg
6365c10afb9Smrg    case PM_GetProxyAddrReply:
6375c10afb9Smrg
6385c10afb9Smrg    {
6395c10afb9Smrg	pmGetProxyAddrReplyMsg 	*pMsg;
6405c10afb9Smrg	char			*pData, *pStart;
6415c10afb9Smrg	char			*addr = NULL, *error = NULL;
6425c10afb9Smrg
6435c10afb9Smrg#if 0 /* No-op */
6445c10afb9Smrg	CHECK_AT_LEAST_SIZE (iceConn, pmConn->pmOpcode, opcode,
6455c10afb9Smrg	    length, SIZEOF (pmGetProxyAddrReplyMsg), IceFatalToProtocol);
6465c10afb9Smrg#endif
6475c10afb9Smrg
6485c10afb9Smrg	IceReadCompleteMessage (iceConn, SIZEOF (pmGetProxyAddrReplyMsg),
6495c10afb9Smrg	    pmGetProxyAddrReplyMsg, pMsg, pStart);
6505c10afb9Smrg
6515c10afb9Smrg	if (!IceValidIO (iceConn))
6525c10afb9Smrg	{
6535c10afb9Smrg	    IceDisposeCompleteMessage (iceConn, pStart);
6545c10afb9Smrg	    return;
6555c10afb9Smrg	}
6565c10afb9Smrg
6575c10afb9Smrg	pData = pStart;
6585c10afb9Smrg
6595c10afb9Smrg	SKIP_STRING (pData, swap);		/* proxy-address */
6605c10afb9Smrg	SKIP_STRING (pData, swap);		/* failure-reason */
6615c10afb9Smrg
6625c10afb9Smrg	CHECK_COMPLETE_SIZE (iceConn, pmConn->pmOpcode, opcode,
6635c10afb9Smrg	    length, pData - pStart + SIZEOF (pmGetProxyAddrReplyMsg),
6645c10afb9Smrg	    pStart, IceFatalToProtocol);
6655c10afb9Smrg
6665c10afb9Smrg	pData = pStart;
6675c10afb9Smrg
6685c10afb9Smrg	EXTRACT_STRING (pData, swap, addr);
6695c10afb9Smrg	EXTRACT_STRING (pData, swap, error);
6705c10afb9Smrg
6715c10afb9Smrg	if (verbose) {
6725c10afb9Smrg	    printf ("Got GetProxyAddrReply from proxy %d, status = %d, ",
6735c10afb9Smrg		    IceConnectionNumber(iceConn), pMsg->status);
6745c10afb9Smrg	    if (pMsg->status == PM_Success)
6755c10afb9Smrg		printf ("addr = %s\n", addr);
6765c10afb9Smrg	    else
6775c10afb9Smrg		printf ("error = %s\n", error);
6785c10afb9Smrg	}
6795c10afb9Smrg
6805c10afb9Smrg	{ /* Ignore any unsolicited replies so we don't get further confused */
6815c10afb9Smrg	    running_proxy *proxy = ProxyForPMconn(pmConn);
6825c10afb9Smrg
6835c10afb9Smrg	    if (!proxy || !proxy->requests)
6845c10afb9Smrg	    {
6855c10afb9Smrg		if (verbose)
6865c10afb9Smrg		    fprintf (stderr, "Received unsolicited GetProxyAddrReply from proxy %d; ignoring it.\n",
6875c10afb9Smrg			     IceConnectionNumber(iceConn));
6885c10afb9Smrg
6895c10afb9Smrg		IceDisposeCompleteMessage (iceConn, pStart);
6905c10afb9Smrg		break;
6915c10afb9Smrg	    }
6925c10afb9Smrg	}
6935c10afb9Smrg
6945c10afb9Smrg	switch (pMsg->status) {
6955c10afb9Smrg
6965c10afb9Smrg	case PM_Success:
6975c10afb9Smrg	{
6985c10afb9Smrg	    /*
6995c10afb9Smrg	     * Now send the GetProxyAddr reply to xfindproxy.
7005c10afb9Smrg	     */
7015c10afb9Smrg
7025c10afb9Smrg	    SendGetProxyAddrReply (
7035c10afb9Smrg		PopRequestorQueue (pmConn, True, True /* free proxy list */),
7045c10afb9Smrg		PM_Success /* status */, addr, NULL);
7055c10afb9Smrg
7065c10afb9Smrg	    break;
7075c10afb9Smrg	}
7085c10afb9Smrg
7095c10afb9Smrg	case PM_Unable:
7105c10afb9Smrg	{
7115c10afb9Smrg	    running_proxy_list *proxyList;
7125c10afb9Smrg	    char *serviceName, *serverAddress, *hostAddress, *startOptions;
7135c10afb9Smrg	    PMconn *requestor;
7145c10afb9Smrg	    int authLen;
7155c10afb9Smrg	    char *authName;
7165c10afb9Smrg	    char *authData;
7175c10afb9Smrg
7185c10afb9Smrg	    {
7195c10afb9Smrg		running_proxy *proxy = ProxyForPMconn(pmConn);
7205c10afb9Smrg		if (proxy)
7215c10afb9Smrg		    proxy->refused_service = True;
7225c10afb9Smrg		else
7235c10afb9Smrg		    fputs("Internal error: received GetProxyAddrReply from an unknown proxy\n", stderr);
7245c10afb9Smrg	    }
7255c10afb9Smrg
7265c10afb9Smrg	    if (! PeekRequestorQueue (pmConn, &requestor,
7275c10afb9Smrg				      &proxyList, &serviceName, &serverAddress,
7285c10afb9Smrg				      &hostAddress, &startOptions,
7295c10afb9Smrg				      &authLen, &authName, &authData)) {
7305c10afb9Smrg		if (verbose)
7315c10afb9Smrg		    fputs("Received GetProxyAddrReply from a proxy with no requests\n", stderr);
7325c10afb9Smrg
7335c10afb9Smrg		proxyList = NULL;
7345c10afb9Smrg		serviceName = "?unknown service--internal error";
7355c10afb9Smrg	    }
7365c10afb9Smrg
7375c10afb9Smrg	    if (proxyList && (proxyList->current < proxyList->count - 1))
7385c10afb9Smrg	    {
7395c10afb9Smrg		/*
7405c10afb9Smrg		 * Ask the next running proxy if it can service this request.
7415c10afb9Smrg		 */
7425c10afb9Smrg		running_proxy *nextProxy;
7435c10afb9Smrg
7445c10afb9Smrg		proxyList->current++;
7455c10afb9Smrg		nextProxy = proxyList->list[proxyList->current];
7465c10afb9Smrg
7475c10afb9Smrg		if (nextProxy->pmConn != NULL) {
7485c10afb9Smrg		    /* send only if the proxy has started */
7495c10afb9Smrg		    SendGetProxyAddr (nextProxy->pmConn, serviceName,
7505c10afb9Smrg				      serverAddress, hostAddress, startOptions,
7515c10afb9Smrg				      authLen, authName, authData);
7525c10afb9Smrg		}
7535c10afb9Smrg
7545c10afb9Smrg		PushRequestorQueue (nextProxy, requestor, proxyList,
7555c10afb9Smrg	            serviceName, serverAddress, hostAddress, startOptions,
7565c10afb9Smrg		    authLen, authName, authData);
7575c10afb9Smrg
7585c10afb9Smrg		PopRequestorQueue (pmConn, False, False);
7595c10afb9Smrg	    }
7605c10afb9Smrg	    else
7615c10afb9Smrg	    {
7625c10afb9Smrg		/*
7635c10afb9Smrg		 * Start a new proxy.
7645c10afb9Smrg		 */
7655c10afb9Smrg
7665c10afb9Smrg		running_proxy *runningProxy = NULL;
7675c10afb9Smrg		char *startCommand;
7685c10afb9Smrg		char *proxyAddress;
7695c10afb9Smrg		Bool managed;
7705c10afb9Smrg
7715c10afb9Smrg		if (!GetConfig (configFile, serviceName, &managed,
7725c10afb9Smrg	            &startCommand, &proxyAddress))
7735c10afb9Smrg		{
7745c10afb9Smrg		    SendGetProxyAddrReply (requestor, PM_Failure,
7755c10afb9Smrg		        NULL, "Could not read proxy manager config file");
7765c10afb9Smrg		}
7775c10afb9Smrg		else
7785c10afb9Smrg		{
7795c10afb9Smrg		    runningProxy = StartNewProxy (serviceName, startCommand);
7805c10afb9Smrg
7815c10afb9Smrg		    if (runningProxy)
7825c10afb9Smrg		    {
7835c10afb9Smrg			PushRequestorQueue (runningProxy,
7845c10afb9Smrg			    requestor, proxyList,
7855c10afb9Smrg			    serviceName, serverAddress,
7865c10afb9Smrg			    hostAddress, startOptions,
7875c10afb9Smrg			    authLen, authName, authData);
7885c10afb9Smrg		    }
7895c10afb9Smrg		    else
7905c10afb9Smrg		    {
7915c10afb9Smrg			SendGetProxyAddrReply (pmConn, PM_Failure,
7925c10afb9Smrg		            NULL, "Can't start new proxy");
7935c10afb9Smrg		    }
7945c10afb9Smrg		}
7955c10afb9Smrg
7965c10afb9Smrg		if (startCommand)
7975c10afb9Smrg		    free (startCommand);
7985c10afb9Smrg		if (proxyAddress)
7995c10afb9Smrg		    free (proxyAddress);
8005c10afb9Smrg
8015c10afb9Smrg		PopRequestorQueue (pmConn, False,
8025c10afb9Smrg		    runningProxy ? False : True /* free proxy list */);
8035c10afb9Smrg	    }
8045c10afb9Smrg	    break;
8055c10afb9Smrg	}
8065c10afb9Smrg
8075c10afb9Smrg	default:
8085c10afb9Smrg	    if (verbose && pMsg->status != PM_Unable)
8095c10afb9Smrg		fprintf(stderr,
8105c10afb9Smrg			"Error: proxy returned unrecognized status: %d\n",
8115c10afb9Smrg			pMsg->status);
8125c10afb9Smrg	    /* FALLTHROUGH */
8135c10afb9Smrg
8145c10afb9Smrg	case PM_Failure:
8155c10afb9Smrg	    SendGetProxyAddrReply (
8165c10afb9Smrg		PopRequestorQueue (pmConn, True, True /* free proxy list */),
8175c10afb9Smrg		pMsg->status, NULL, error);
8185c10afb9Smrg	}
8195c10afb9Smrg
8205c10afb9Smrg	IceDisposeCompleteMessage (iceConn, pStart);
8215c10afb9Smrg
8225c10afb9Smrg	/* see if there was more work queued for this proxy */
8235c10afb9Smrg	{
8245c10afb9Smrg	    char *serviceName, *serverAddress, *hostAddress, *startOptions;
8255c10afb9Smrg	    int authLen;
8265c10afb9Smrg	    char *authName, *authData;
8275c10afb9Smrg
8285c10afb9Smrg	    if (PeekRequestorQueue(pmConn,
8295c10afb9Smrg				   NULL, NULL, &serviceName,
8305c10afb9Smrg				   &serverAddress, &hostAddress, &startOptions,
8315c10afb9Smrg				   &authLen, &authName, &authData)) {
8325c10afb9Smrg		SendGetProxyAddr(pmConn,
8335c10afb9Smrg				 serviceName, serverAddress,
8345c10afb9Smrg				 hostAddress, startOptions,
8355c10afb9Smrg				 authLen, authName, authData);
8365c10afb9Smrg	    }
8375c10afb9Smrg	}
8385c10afb9Smrg
8395c10afb9Smrg	if (addr)
8405c10afb9Smrg	    free (addr);
8415c10afb9Smrg	if (error)
8425c10afb9Smrg	    free (error);
8435c10afb9Smrg
8445c10afb9Smrg	break;
8455c10afb9Smrg    }
8465c10afb9Smrg
8475c10afb9Smrg    case PM_Error:
8485c10afb9Smrg    {
8495c10afb9Smrg	iceErrorMsg *pMsg;
8505c10afb9Smrg	char *pStart;
8515c10afb9Smrg
8525c10afb9Smrg	CHECK_AT_LEAST_SIZE (iceConn, pmConn->pmOpcode, PM_Error, length,
8535c10afb9Smrg			     sizeof(iceErrorMsg), IceFatalToProtocol);
8545c10afb9Smrg
8555c10afb9Smrg	IceReadCompleteMessage (iceConn, SIZEOF (iceErrorMsg),
8565c10afb9Smrg				iceErrorMsg, pMsg, pStart);
8575c10afb9Smrg
8585c10afb9Smrg	if (!IceValidIO (iceConn))
8595c10afb9Smrg	{
8605c10afb9Smrg	    IceDisposeCompleteMessage (iceConn, pStart);
8615c10afb9Smrg	    return;
8625c10afb9Smrg	}
8635c10afb9Smrg
8645c10afb9Smrg	if (swap)
8655c10afb9Smrg	{
8665c10afb9Smrg	    pMsg->errorClass = lswaps (pMsg->errorClass);
8675c10afb9Smrg	    pMsg->offendingSequenceNum = lswapl (pMsg->offendingSequenceNum);
8685c10afb9Smrg	}
8695c10afb9Smrg
8705c10afb9Smrg	fprintf(stderr, "Received ICE Error: class=0x%x\n  offending minor opcode=%d, severity=%d, sequence=%d\n",
8715c10afb9Smrg		pMsg->errorClass, pMsg->offendingMinorOpcode, pMsg->severity,
8725c10afb9Smrg		(int)pMsg->offendingSequenceNum);
8735c10afb9Smrg
8745c10afb9Smrg	IceDisposeCompleteMessage (iceConn, pStart);
8755c10afb9Smrg
8765c10afb9Smrg	break;
8775c10afb9Smrg    }
8785c10afb9Smrg
8795c10afb9Smrg    default:
8805c10afb9Smrg    {
8815c10afb9Smrg	_IceErrorBadMinor (iceConn, pmConn->pmOpcode, opcode, IceCanContinue);
8825c10afb9Smrg	_IceReadSkip (iceConn, length << 3);
8835c10afb9Smrg	break;
8845c10afb9Smrg    }
8855c10afb9Smrg    }
8865c10afb9Smrg}
8875c10afb9Smrg
8885c10afb9Smrgvoid
889b3078addSmrgPMSetupProcessMessages(IceConn iceConn, IcePointer clientData, int opcode,
890b3078addSmrg		       unsigned long length, Bool swap,
891b3078addSmrg		       IceReplyWaitInfo *replyWait, Bool *replyReadyRet)
8925c10afb9Smrg
8935c10afb9Smrg{
8945c10afb9Smrg    assert (replyWait == NULL);
8955c10afb9Smrg
8965c10afb9Smrg    PMReplyProcessMessages (iceConn, clientData, opcode, length, swap);
8975c10afb9Smrg}
8985c10afb9Smrg
8995c10afb9Smrg
9005c10afb9Smrgvoid
901b3078addSmrgForwardRequest(PMconn *requestor, char *serviceName, char *serverAddress,
902b3078addSmrg	       char *hostAddress, char *startOptions, int authLen,
903b3078addSmrg	       char *authName, char *authData)
9045c10afb9Smrg{
9055c10afb9Smrg    running_proxy_list	*proxyList;
9065c10afb9Smrg    running_proxy	*runningProxy = NULL;
9075c10afb9Smrg    int			pushRequest = 0;
9085c10afb9Smrg
9095c10afb9Smrg    if ((proxyList = GetRunningProxyList (
9105c10afb9Smrg	serviceName, serverAddress)) != NULL)
9115c10afb9Smrg    {
9125c10afb9Smrg	while (proxyList->current < proxyList->count) {
9135c10afb9Smrg	    runningProxy = proxyList->list[proxyList->current];
9145c10afb9Smrg
9155c10afb9Smrg	    if (runningProxy->pmConn != NULL) {
9165c10afb9Smrg		SendGetProxyAddr (runningProxy->pmConn, serviceName,
9175c10afb9Smrg				  serverAddress, hostAddress, NULL,
9185c10afb9Smrg				  authLen, authName, authData);
9195c10afb9Smrg		break;
9205c10afb9Smrg	    }
9215c10afb9Smrg	    proxyList->current++;
9225c10afb9Smrg	}
9235c10afb9Smrg
9245c10afb9Smrg	pushRequest = 1;
9255c10afb9Smrg    }
9265c10afb9Smrg    else
9275c10afb9Smrg    {
9285c10afb9Smrg	Bool managed;
9295c10afb9Smrg	char *startCommand;
9305c10afb9Smrg	char *proxyAddress;
9315c10afb9Smrg
9325c10afb9Smrg	if (!GetConfig (configFile, serviceName, &managed,
9335c10afb9Smrg	    &startCommand, &proxyAddress))
9345c10afb9Smrg	{
9355c10afb9Smrg	    SendGetProxyAddrReply (requestor, PM_Failure,
9365c10afb9Smrg		NULL, "Could not find requested service");
9375c10afb9Smrg	}
9385c10afb9Smrg	else
9395c10afb9Smrg	{
9405c10afb9Smrg	    if (managed)
9415c10afb9Smrg	    {
9425c10afb9Smrg		runningProxy = StartNewProxy (serviceName, startCommand);
9435c10afb9Smrg
9445c10afb9Smrg		if (runningProxy)
9455c10afb9Smrg		    pushRequest = 1;
9465c10afb9Smrg		else
9475c10afb9Smrg		{
9485c10afb9Smrg		    SendGetProxyAddrReply (requestor, PM_Failure,
9495c10afb9Smrg			NULL, "Can't start new proxy");
9505c10afb9Smrg		}
9515c10afb9Smrg	    }
9525c10afb9Smrg	    else
9535c10afb9Smrg	    {
9545c10afb9Smrg		/*
9555c10afb9Smrg		 * We have the unmanged proxy's address; now forward
9565c10afb9Smrg		 * the request to it.
9575c10afb9Smrg		 */
9585c10afb9Smrg
9595c10afb9Smrg		runningProxy = ConnectToProxy (PMOriginatorOpcode,
9605c10afb9Smrg					       serviceName, proxyAddress);
9615c10afb9Smrg
9625c10afb9Smrg		if (runningProxy) {
9635c10afb9Smrg		    SendGetProxyAddr (runningProxy->pmConn,
9645c10afb9Smrg				      serviceName, serverAddress,
9655c10afb9Smrg				      hostAddress, startOptions,
9665c10afb9Smrg				      authLen, authName, authData);
9675c10afb9Smrg		    pushRequest = 1;
9685c10afb9Smrg		}
9695c10afb9Smrg		else
9705c10afb9Smrg		{
9715c10afb9Smrg		    /* %%% We should reread the config file and look
9725c10afb9Smrg		     * for another proxy address before giving up.
9735c10afb9Smrg		     */
9745c10afb9Smrg		    SendGetProxyAddrReply (requestor, PM_Failure,
9755c10afb9Smrg			NULL, "Can't connect to proxy");
9765c10afb9Smrg		}
9775c10afb9Smrg	    }
9785c10afb9Smrg
9795c10afb9Smrg	    if (startCommand)
9805c10afb9Smrg		free (startCommand);
9815c10afb9Smrg	    if (proxyAddress)
9825c10afb9Smrg		free (proxyAddress);
9835c10afb9Smrg	}
9845c10afb9Smrg    }
9855c10afb9Smrg
9865c10afb9Smrg    if (pushRequest)
9875c10afb9Smrg    {
9885c10afb9Smrg	PushRequestorQueue (runningProxy, requestor, proxyList,
9895c10afb9Smrg	    serviceName, serverAddress, hostAddress, startOptions,
9905c10afb9Smrg	    authLen, authName, authData);
9915c10afb9Smrg    }
9925c10afb9Smrg}
9935c10afb9Smrg
9945c10afb9Smrg
9955c10afb9Smrg/* ARGSUSED */
9965c10afb9Smrgvoid
997b3078addSmrg_XtProcessIceMsgProc(XtPointer client_data, int *source, XtInputId *id)
9985c10afb9Smrg{
9995c10afb9Smrg    IceConn			ice_conn = (IceConn) client_data;
10005c10afb9Smrg    IceProcessMessagesStatus	status;
10015c10afb9Smrg
10025c10afb9Smrg    status = IceProcessMessages (ice_conn, NULL, NULL);
10035c10afb9Smrg
10045c10afb9Smrg    if (status == IceProcessMessagesIOError)
10055c10afb9Smrg    {
10065c10afb9Smrg	Bool activeReqs;
10075c10afb9Smrg
10085c10afb9Smrg	ProxyGone (ice_conn, &activeReqs);
10095c10afb9Smrg	IceSetShutdownNegotiation (ice_conn, False);
10105c10afb9Smrg	IceCloseConnection (ice_conn);
10115c10afb9Smrg    }
10125c10afb9Smrg}
10135c10afb9Smrg
10145c10afb9Smrg
10155c10afb9Smrgvoid
1016b3078addSmrg_XtIceWatchProc(IceConn ice_conn, IcePointer client_data,
1017b3078addSmrg		Bool opening, IcePointer *watch_data)
10185c10afb9Smrg
10195c10afb9Smrg{
10205c10afb9Smrg    if (opening)
10215c10afb9Smrg    {
10225c10afb9Smrg	XtAppContext appContext = (XtAppContext) client_data;
10235c10afb9Smrg
10245c10afb9Smrg	*watch_data = (IcePointer) XtAppAddInput (
10255c10afb9Smrg	    appContext,
10265c10afb9Smrg	    IceConnectionNumber (ice_conn),
10275c10afb9Smrg            (XtPointer) XtInputReadMask,
10285c10afb9Smrg	    _XtProcessIceMsgProc,
10295c10afb9Smrg	    (XtPointer) ice_conn);
10305c10afb9Smrg    }
10315c10afb9Smrg    else
10325c10afb9Smrg    {
10335c10afb9Smrg	XtRemoveInput ((XtInputId) *watch_data);
10345c10afb9Smrg    }
10355c10afb9Smrg}
10365c10afb9Smrg
10375c10afb9Smrg
10385c10afb9SmrgStatus
1039b3078addSmrgInitWatchProcs(XtAppContext appContext)
10405c10afb9Smrg
10415c10afb9Smrg{
10425c10afb9Smrg    return (IceAddConnectionWatch (_XtIceWatchProc, (IcePointer) appContext));
10435c10afb9Smrg}
10445c10afb9Smrg
10455c10afb9Smrg
10465c10afb9Smrg/*
10475c10afb9Smrg * The real way to handle IO errors is to check the return status
10485c10afb9Smrg * of IceProcessMessages.  xsm properly does this.
10495c10afb9Smrg *
10505c10afb9Smrg * Unfortunately, a design flaw exists in the ICE library in which
10515c10afb9Smrg * a default IO error handler is invoked if no IO error handler is
10525c10afb9Smrg * installed.  This default handler exits.  We must avoid this.
10535c10afb9Smrg *
10545c10afb9Smrg * To get around this problem, we install an IO error handler that
10555c10afb9Smrg * does a little magic.  Since a previous IO handler might have been
10565c10afb9Smrg * installed, when we install our IO error handler, we do a little
10575c10afb9Smrg * trick to get both the previous IO error handler and the default
10585c10afb9Smrg * IO error handler.  When our IO error handler is called, if the
10595c10afb9Smrg * previous handler is not the default handler, we call it.  This
10605c10afb9Smrg * way, everyone's IO error handler gets called except the stupid
10615c10afb9Smrg * default one which does an exit!
10625c10afb9Smrg */
10635c10afb9Smrg
10645c10afb9Smrgstatic IceIOErrorHandler prev_handler;
10655c10afb9Smrg
10665c10afb9Smrgvoid
1067b3078addSmrgMyIoErrorHandler(IceConn ice_conn)
10685c10afb9Smrg{
10695c10afb9Smrg    if (prev_handler)
10705c10afb9Smrg	(*prev_handler) (ice_conn);
10715c10afb9Smrg}
10725c10afb9Smrg
10735c10afb9Smrgvoid
1074b3078addSmrgInstallIOErrorHandler(void)
10755c10afb9Smrg{
10765c10afb9Smrg    IceIOErrorHandler default_handler;
10775c10afb9Smrg
10785c10afb9Smrg    prev_handler = IceSetIOErrorHandler (NULL);
10795c10afb9Smrg    default_handler = IceSetIOErrorHandler (MyIoErrorHandler);
10805c10afb9Smrg    if (prev_handler == default_handler)
10815c10afb9Smrg	prev_handler = NULL;
10825c10afb9Smrg}
10835c10afb9Smrg
10845c10afb9Smrg
10855c10afb9Smrg/*
10865c10afb9Smrg * Since proxy manager does not authenticate connections, we disable
10875c10afb9Smrg * authentication by always returning true in the host based auth proc.
10885c10afb9Smrg */
10895c10afb9Smrg
10905c10afb9SmrgBool
1091b3078addSmrgHostBasedAuthProc(char *hostname)
10925c10afb9Smrg{
10935c10afb9Smrg    return (1);
10945c10afb9Smrg}
1095