1146 lines
27 KiB
C
1146 lines
27 KiB
C
|
/* $Xorg: main.c,v 1.6 2001/02/09 02:05:34 xorgcvs Exp $ */
|
|||
|
|
|||
|
/*
|
|||
|
Copyright 1996, 1998 The Open Group
|
|||
|
|
|||
|
Permission to use, copy, modify, distribute, and sell this software and its
|
|||
|
documentation for any purpose is hereby granted without fee, provided that
|
|||
|
the above copyright notice appear in all copies and that both that
|
|||
|
copyright notice and this permission notice appear in supporting
|
|||
|
documentation.
|
|||
|
|
|||
|
The above copyright notice and this permission notice shall be included
|
|||
|
in all copies or substantial portions of the Software.
|
|||
|
|
|||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|||
|
IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|||
|
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|||
|
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|||
|
OTHER DEALINGS IN THE SOFTWARE.
|
|||
|
|
|||
|
Except as contained in this notice, the name of The Open Group shall
|
|||
|
not be used in advertising or otherwise to promote the sale, use or
|
|||
|
other dealings in this Software without prior written authorization
|
|||
|
from The Open Group.
|
|||
|
*/
|
|||
|
/* $XFree86: xc/programs/proxymngr/main.c,v 1.8tsi Exp $ */
|
|||
|
|
|||
|
#include <stdlib.h>
|
|||
|
#include "pmint.h"
|
|||
|
#include <X11/StringDefs.h>
|
|||
|
#include <X11/Intrinsic.h>
|
|||
|
#include <X11/ICE/ICEmsg.h>
|
|||
|
#include <X11/ICE/ICEproto.h>
|
|||
|
#include <X11/PM/PMproto.h>
|
|||
|
#include <X11/PM/PM.h>
|
|||
|
#include "pmdb.h"
|
|||
|
#include "config.h"
|
|||
|
#include <assert.h>
|
|||
|
|
|||
|
#include <netinet/in.h>
|
|||
|
#include <arpa/inet.h>
|
|||
|
#include <sys/socket.h>
|
|||
|
#include <netdb.h>
|
|||
|
|
|||
|
static int PMprotocolSetupProc ( IceConn iceConn, int majorVersion,
|
|||
|
int minorVersion, char *vendor,
|
|||
|
char *release, IcePointer *clientDataRet,
|
|||
|
char **failureReasonRet );
|
|||
|
static void SendGetProxyAddr ( PMconn *pmConn, char *serviceName,
|
|||
|
char *serverAddress, char *hostAddress,
|
|||
|
char *startOptions, int authLen,
|
|||
|
char *authName, char *authData );
|
|||
|
|
|||
|
static int PMAcceptorOpcode;
|
|||
|
static int PMOriginatorOpcode;
|
|||
|
|
|||
|
int PMversionCount = 1;
|
|||
|
IcePaVersionRec PMReplyVersions[] = {{PM_MAJOR_VERSION, PM_MINOR_VERSION,
|
|||
|
PMReplyProcessMessages}};
|
|||
|
IcePoVersionRec PMSetupVersions[] = {{PM_MAJOR_VERSION, PM_MINOR_VERSION,
|
|||
|
PMSetupProcessMessages}};
|
|||
|
|
|||
|
char *PM_VENDOR_STRING = XVENDORNAME;
|
|||
|
char *PM_VENDOR_RELEASE = XORG_RELEASE;
|
|||
|
|
|||
|
int verbose = 0;
|
|||
|
|
|||
|
XtAppContext appContext;
|
|||
|
|
|||
|
#define PM_PORT "6500"
|
|||
|
|
|||
|
char *configFile = NULL;
|
|||
|
|
|||
|
void
|
|||
|
Usage ()
|
|||
|
{
|
|||
|
fprintf (stderr, "Usage: proxymngr [-config file] [-verbose]\n");
|
|||
|
exit (1);
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
SetCloseOnExec (fd)
|
|||
|
int fd;
|
|||
|
{
|
|||
|
#ifdef F_SETFD
|
|||
|
#ifdef FD_CLOEXEC
|
|||
|
(void) fcntl (fd, F_SETFD, FD_CLOEXEC);
|
|||
|
#else
|
|||
|
(void) fcntl (fd, F_SETFD, 1);
|
|||
|
#endif /* FD_CLOEXEC */
|
|||
|
#endif /* F_SETFD */
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* Main program
|
|||
|
*/
|
|||
|
|
|||
|
int
|
|||
|
main (int argc, char *argv[])
|
|||
|
{
|
|||
|
IceListenObj *listenObjs;
|
|||
|
int numTransports, i;
|
|||
|
char errormsg[256];
|
|||
|
char *networkIds, *p;
|
|||
|
|
|||
|
for (i = 1; i < argc; i++)
|
|||
|
{
|
|||
|
if (strcmp (argv[i], "-config") == 0)
|
|||
|
{
|
|||
|
if (++i < argc)
|
|||
|
configFile = argv[i];
|
|||
|
else
|
|||
|
Usage ();
|
|||
|
}
|
|||
|
else if (strcmp(argv[i], "-verbose") == 0)
|
|||
|
{
|
|||
|
verbose = 1;
|
|||
|
}
|
|||
|
else
|
|||
|
Usage ();
|
|||
|
}
|
|||
|
|
|||
|
if (!configFile)
|
|||
|
configFile = CONFIG_FILE;
|
|||
|
|
|||
|
if (verbose)
|
|||
|
fprintf (stderr, "config file = %s\n", configFile);
|
|||
|
|
|||
|
/*
|
|||
|
* Install an IO error handler.
|
|||
|
*/
|
|||
|
InstallIOErrorHandler ();
|
|||
|
|
|||
|
/*
|
|||
|
* Register support for PROXY_MANAGEMENT.
|
|||
|
*/
|
|||
|
|
|||
|
/* For Managed proxies, the proxy does the Setup */
|
|||
|
if ((PMAcceptorOpcode = IceRegisterForProtocolReply (
|
|||
|
PM_PROTOCOL_NAME, PM_VENDOR_STRING, PM_VENDOR_RELEASE,
|
|||
|
PMversionCount, PMReplyVersions,
|
|||
|
0, /* authcount */
|
|||
|
NULL, /* authnames */
|
|||
|
NULL, /* authprocs */
|
|||
|
HostBasedAuthProc,
|
|||
|
PMprotocolSetupProc,
|
|||
|
NULL, /* protocolActivateProc */
|
|||
|
NULL /* IceIOErrorProc */ )) < 0)
|
|||
|
{
|
|||
|
fprintf (stderr,
|
|||
|
"Could not register PROXY_MANAGEMENT protocol reply with ICE");
|
|||
|
exit (1);
|
|||
|
}
|
|||
|
|
|||
|
/* For Unmanaged proxies, we do the Setup
|
|||
|
* ICElib doesn't specify that the same opCode will be returned
|
|||
|
* so don't bet on it.
|
|||
|
*/
|
|||
|
if ((PMOriginatorOpcode = IceRegisterForProtocolSetup (
|
|||
|
PM_PROTOCOL_NAME, PM_VENDOR_STRING, PM_VENDOR_RELEASE,
|
|||
|
PMversionCount, PMSetupVersions,
|
|||
|
0, /* authcount */
|
|||
|
NULL, /* authnames */
|
|||
|
NULL, /* authprocs */
|
|||
|
NULL /* IceIOErrorProc */ )) < 0)
|
|||
|
{
|
|||
|
fprintf (stderr,
|
|||
|
"Could not register PROXY_MANAGEMENT protocol setup with ICE");
|
|||
|
exit (1);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
if (!IceListenForWellKnownConnections (
|
|||
|
PM_PORT, &numTransports, &listenObjs, 256, errormsg))
|
|||
|
{
|
|||
|
fprintf (stderr, "%s\n", errormsg);
|
|||
|
exit (1);
|
|||
|
}
|
|||
|
|
|||
|
networkIds = IceComposeNetworkIdList (numTransports, listenObjs);
|
|||
|
p = (char *) malloc(sizeof ("PROXY_MANAGER") + strlen(networkIds) + 2);
|
|||
|
sprintf (p, "PROXY_MANAGER=%s", networkIds);
|
|||
|
putenv (p);
|
|||
|
printf ("%s\n", p);
|
|||
|
free (networkIds);
|
|||
|
|
|||
|
appContext = XtCreateApplicationContext ();
|
|||
|
|
|||
|
InitWatchProcs (appContext);
|
|||
|
|
|||
|
for (i = 0; i < numTransports; i++)
|
|||
|
{
|
|||
|
XtAppAddInput (appContext,
|
|||
|
IceGetListenConnectionNumber (listenObjs[i]),
|
|||
|
(XtPointer) XtInputReadMask,
|
|||
|
NewConnectionXtProc, (XtPointer) listenObjs[i]);
|
|||
|
|
|||
|
IceSetHostBasedAuthProc (listenObjs[i], HostBasedAuthProc);
|
|||
|
|
|||
|
SetCloseOnExec (IceGetListenConnectionNumber (listenObjs[i]));
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* Main loop
|
|||
|
*/
|
|||
|
XtAppMainLoop (appContext);
|
|||
|
exit (0);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
* Xt callback invoked when a client attempts to connect.
|
|||
|
*/
|
|||
|
|
|||
|
/* ARGSUSED */
|
|||
|
void
|
|||
|
NewConnectionXtProc (client_data, source, id)
|
|||
|
|
|||
|
XtPointer client_data;
|
|||
|
int *source;
|
|||
|
XtInputId *id;
|
|||
|
|
|||
|
{
|
|||
|
IceConn ice_conn;
|
|||
|
char *connstr;
|
|||
|
IceAcceptStatus status;
|
|||
|
|
|||
|
ice_conn = IceAcceptConnection((IceListenObj) client_data, &status);
|
|||
|
if (! ice_conn) {
|
|||
|
if (verbose)
|
|||
|
printf ("IceAcceptConnection failed\n");
|
|||
|
} else {
|
|||
|
IceConnectStatus cstatus;
|
|||
|
|
|||
|
/*
|
|||
|
* Mark this fd to be closed upon exec
|
|||
|
*/
|
|||
|
SetCloseOnExec (IceConnectionNumber (ice_conn));
|
|||
|
|
|||
|
while ((cstatus = IceConnectionStatus (ice_conn))==IceConnectPending) {
|
|||
|
XtAppProcessEvent (appContext, XtIMAll);
|
|||
|
}
|
|||
|
|
|||
|
if (cstatus == IceConnectAccepted) {
|
|||
|
if (verbose) {
|
|||
|
printf ("ICE Connection opened by client, IceConn fd = %d, ",
|
|||
|
IceConnectionNumber (ice_conn));
|
|||
|
connstr = IceConnectionString (ice_conn);
|
|||
|
printf ("Accept at networkId %s\n", connstr);
|
|||
|
free (connstr);
|
|||
|
printf ("\n");
|
|||
|
}
|
|||
|
} else {
|
|||
|
if (verbose)
|
|||
|
{
|
|||
|
if (cstatus == IceConnectIOError)
|
|||
|
printf ("IO error opening ICE Connection!\n");
|
|||
|
else
|
|||
|
printf ("ICE Connection rejected!\n");
|
|||
|
}
|
|||
|
|
|||
|
IceCloseConnection (ice_conn);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
* See ConnectToProxy() if you change any of the pmConn structure
|
|||
|
*/
|
|||
|
static Status
|
|||
|
PMprotocolSetupProc (iceConn,
|
|||
|
majorVersion, minorVersion, vendor, release,
|
|||
|
clientDataRet, failureReasonRet)
|
|||
|
|
|||
|
IceConn iceConn;
|
|||
|
int majorVersion;
|
|||
|
int minorVersion;
|
|||
|
char *vendor;
|
|||
|
char *release;
|
|||
|
IcePointer *clientDataRet;
|
|||
|
char **failureReasonRet;
|
|||
|
|
|||
|
{
|
|||
|
/*
|
|||
|
* Allocate new pmConn.
|
|||
|
*/
|
|||
|
|
|||
|
static char standardError[] = "Could not allocate memory for new client";
|
|||
|
PMconn *pmConn;
|
|||
|
|
|||
|
if ((pmConn = (PMconn *) malloc (sizeof (PMconn))) == NULL)
|
|||
|
{
|
|||
|
if (verbose)
|
|||
|
fprintf (stderr, "%s\n", standardError);
|
|||
|
|
|||
|
*failureReasonRet = standardError;
|
|||
|
return (0);
|
|||
|
}
|
|||
|
|
|||
|
pmConn->iceConn = iceConn;
|
|||
|
pmConn->pmOpcode = PMAcceptorOpcode;
|
|||
|
pmConn->proto_major_version = majorVersion;
|
|||
|
pmConn->proto_minor_version = minorVersion;
|
|||
|
pmConn->vendor = vendor;
|
|||
|
pmConn->release = release;
|
|||
|
|
|||
|
*clientDataRet = (IcePointer) pmConn;
|
|||
|
|
|||
|
return (1);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
static void
|
|||
|
SendGetProxyAddr (
|
|||
|
PMconn *pmConn,
|
|||
|
char *serviceName,
|
|||
|
char *serverAddress,
|
|||
|
char *hostAddress,
|
|||
|
char *startOptions,
|
|||
|
int authLen,
|
|||
|
char *authName,
|
|||
|
char *authData)
|
|||
|
|
|||
|
{
|
|||
|
IceConn iceConn = pmConn->iceConn;
|
|||
|
pmGetProxyAddrMsg *pMsg;
|
|||
|
char *pData;
|
|||
|
int len;
|
|||
|
|
|||
|
if (verbose) {
|
|||
|
printf ("Sending GetProxyAddr to proxy %d, serviceName = %s, serverAddr = %s\n",
|
|||
|
IceConnectionNumber(iceConn), serviceName, serverAddress);
|
|||
|
printf (" hostAddr = %s, options = %s, authLen = %d\n",
|
|||
|
hostAddress ? hostAddress : "",
|
|||
|
startOptions ? startOptions : "",
|
|||
|
authLen);
|
|||
|
if (authLen > 0)
|
|||
|
printf (" authName = %s\n", authName);
|
|||
|
}
|
|||
|
|
|||
|
len = STRING_BYTES (serviceName) +
|
|||
|
STRING_BYTES (serverAddress) +
|
|||
|
STRING_BYTES (hostAddress) +
|
|||
|
STRING_BYTES (startOptions) +
|
|||
|
(authLen > 0 ? (STRING_BYTES (authName) + authLen) : 0);
|
|||
|
|
|||
|
IceGetHeaderExtra (iceConn, pmConn->pmOpcode, PM_GetProxyAddr,
|
|||
|
SIZEOF (pmGetProxyAddrMsg), WORD64COUNT (len),
|
|||
|
pmGetProxyAddrMsg, pMsg, pData);
|
|||
|
|
|||
|
pMsg->authLen = authLen;
|
|||
|
|
|||
|
STORE_STRING (pData, serviceName);
|
|||
|
STORE_STRING (pData, serverAddress);
|
|||
|
STORE_STRING (pData, hostAddress);
|
|||
|
STORE_STRING (pData, startOptions);
|
|||
|
if (authLen > 0)
|
|||
|
{
|
|||
|
STORE_STRING (pData, authName);
|
|||
|
memcpy (pData, authData, authLen);
|
|||
|
}
|
|||
|
|
|||
|
IceFlush (iceConn);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
void
|
|||
|
SendGetProxyAddrReply (
|
|||
|
PMconn *requestor,
|
|||
|
int status,
|
|||
|
char *addr,
|
|||
|
char *error)
|
|||
|
|
|||
|
{
|
|||
|
int len = STRING_BYTES (addr) + STRING_BYTES (error);
|
|||
|
pmGetProxyAddrReplyMsg *pReply;
|
|||
|
char *pData;
|
|||
|
|
|||
|
if (verbose) {
|
|||
|
fputs ("Replying with ", stderr);
|
|||
|
fputs (status == PM_Success ? "Success: " :
|
|||
|
status == PM_Failure ? "Failure: " :
|
|||
|
status == PM_Unable ? "Unable: " :
|
|||
|
"?unknown status", stderr);
|
|||
|
fputs (status == PM_Success ? addr : error, stderr);
|
|||
|
fputc ('\n', stderr);
|
|||
|
}
|
|||
|
|
|||
|
IceGetHeaderExtra (requestor->iceConn,
|
|||
|
requestor->pmOpcode, PM_GetProxyAddrReply,
|
|||
|
SIZEOF (pmGetProxyAddrReplyMsg), WORD64COUNT (len),
|
|||
|
pmGetProxyAddrReplyMsg, pReply, pData);
|
|||
|
|
|||
|
pReply->status = status;
|
|||
|
|
|||
|
STORE_STRING (pData, addr);
|
|||
|
STORE_STRING (pData, error);
|
|||
|
|
|||
|
IceFlush (requestor->iceConn);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
void
|
|||
|
PMReplyProcessMessages (iceConn, clientData, opcode, length, swap)
|
|||
|
|
|||
|
IceConn iceConn;
|
|||
|
IcePointer clientData;
|
|||
|
int opcode;
|
|||
|
unsigned long length;
|
|||
|
Bool swap;
|
|||
|
|
|||
|
{
|
|||
|
PMconn *pmConn = (PMconn *) clientData;
|
|||
|
|
|||
|
assert(pmConn->iceConn == iceConn);
|
|||
|
|
|||
|
switch (opcode)
|
|||
|
{
|
|||
|
case PM_GetProxyAddr:
|
|||
|
{
|
|||
|
pmGetProxyAddrMsg *pMsg;
|
|||
|
char *pData, *pStart;
|
|||
|
char *serviceName = NULL, *serverAddress = NULL;
|
|||
|
char *hostAddress = NULL, *startOptions = NULL;
|
|||
|
char *authName = NULL, *authData = NULL;
|
|||
|
int authLen;
|
|||
|
|
|||
|
#if 0 /* No-op */
|
|||
|
CHECK_AT_LEAST_SIZE (iceConn, pmConn->pmOpcode, opcode,
|
|||
|
length, SIZEOF (pmGetProxyAddrMsg), IceFatalToProtocol);
|
|||
|
#endif
|
|||
|
|
|||
|
IceReadCompleteMessage (iceConn, SIZEOF (pmGetProxyAddrMsg),
|
|||
|
pmGetProxyAddrMsg, pMsg, pStart);
|
|||
|
|
|||
|
if (!IceValidIO (iceConn))
|
|||
|
{
|
|||
|
IceDisposeCompleteMessage (iceConn, pStart);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
authLen = swap ? lswaps (pMsg->authLen) : pMsg->authLen;
|
|||
|
|
|||
|
pData = pStart;
|
|||
|
|
|||
|
SKIP_STRING (pData, swap); /* proxy-service */
|
|||
|
SKIP_STRING (pData, swap); /* server-address */
|
|||
|
SKIP_STRING (pData, swap); /* host-address */
|
|||
|
SKIP_STRING (pData, swap); /* start-options */
|
|||
|
if (authLen > 0)
|
|||
|
{
|
|||
|
SKIP_STRING (pData, swap); /* auth-name */
|
|||
|
pData += (authLen + PAD64 (authLen)); /* auth-data */
|
|||
|
}
|
|||
|
|
|||
|
CHECK_COMPLETE_SIZE (iceConn, pmConn->pmOpcode, opcode,
|
|||
|
length, pData - pStart + SIZEOF (pmGetProxyAddrMsg),
|
|||
|
pStart, IceFatalToProtocol);
|
|||
|
|
|||
|
pData = pStart;
|
|||
|
|
|||
|
EXTRACT_STRING (pData, swap, serviceName);
|
|||
|
EXTRACT_STRING (pData, swap, serverAddress);
|
|||
|
EXTRACT_STRING (pData, swap, hostAddress);
|
|||
|
EXTRACT_STRING (pData, swap, startOptions);
|
|||
|
if (authLen > 0)
|
|||
|
{
|
|||
|
EXTRACT_STRING (pData, swap, authName);
|
|||
|
authData = (char *) malloc (authLen);
|
|||
|
memcpy (authData, pData, authLen);
|
|||
|
}
|
|||
|
|
|||
|
if (serverAddress)
|
|||
|
{
|
|||
|
/*
|
|||
|
* Assume that if serverAddress is something like :0 or :0.0
|
|||
|
* then the request is for a server on the client's host.
|
|||
|
*
|
|||
|
* However, the proxy handling this request may be on a
|
|||
|
* different host than the client or the client host,
|
|||
|
* proxy host and the server host may all be different,
|
|||
|
* thus a serverAddress of :0 or :0.0 is not useful.
|
|||
|
* Therefore, change serverAddress to use the client's
|
|||
|
* hostname.
|
|||
|
*/
|
|||
|
char *tmpName;
|
|||
|
|
|||
|
tmpName = strrchr (serverAddress, ':');
|
|||
|
|
|||
|
if (tmpName && ((tmpName == serverAddress) ||
|
|||
|
(!strncmp (serverAddress, "unix:", 5))))
|
|||
|
{
|
|||
|
#if defined(IPv6) && defined(AF_INET6)
|
|||
|
struct sockaddr_storage serverSock;
|
|||
|
#else
|
|||
|
struct sockaddr_in serverSock;
|
|||
|
#endif
|
|||
|
int retVal;
|
|||
|
int addrLen = sizeof(serverSock);
|
|||
|
|
|||
|
retVal = getpeername(IceConnectionNumber(iceConn),
|
|||
|
(struct sockaddr *) &serverSock,
|
|||
|
(void *) &addrLen);
|
|||
|
if (!retVal)
|
|||
|
{
|
|||
|
char *canonname = NULL;
|
|||
|
#if defined(IPv6) && defined(AF_INET6)
|
|||
|
char hostname[NI_MAXHOST];
|
|||
|
struct addrinfo *ai = NULL, hints;
|
|||
|
|
|||
|
if (getnameinfo((struct sockaddr *) &serverSock,
|
|||
|
addrLen, hostname, sizeof(hostname), NULL, 0, 0) == 0) {
|
|||
|
(void)memset(&hints, 0, sizeof(hints));
|
|||
|
hints.ai_flags = AI_CANONNAME;
|
|||
|
if (getaddrinfo(hostname, NULL, &hints, &ai) == 0) {
|
|||
|
canonname = ai->ai_canonname;
|
|||
|
} else {
|
|||
|
ai = NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
#else
|
|||
|
struct hostent *hostent;
|
|||
|
|
|||
|
hostent = gethostbyname (inet_ntoa(serverSock.sin_addr));
|
|||
|
|
|||
|
if (hostent && hostent->h_name)
|
|||
|
canonname = hostent->h_name;
|
|||
|
#endif
|
|||
|
if (canonname)
|
|||
|
{
|
|||
|
int len;
|
|||
|
char * pch = strdup (tmpName);
|
|||
|
|
|||
|
len = strlen(canonname) + strlen(tmpName) + 1;
|
|||
|
serverAddress = (char *) realloc (serverAddress, len);
|
|||
|
sprintf (serverAddress, "%s%s", canonname, pch);
|
|||
|
free (pch);
|
|||
|
}
|
|||
|
#if defined(IPv6) && defined(AF_INET6)
|
|||
|
if (ai != NULL)
|
|||
|
freeaddrinfo(ai);
|
|||
|
#endif
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (verbose) {
|
|||
|
printf ("Got GetProxyAddr, serviceName = %s, serverAddr = %s\n",
|
|||
|
serviceName, serverAddress);
|
|||
|
printf (" hostAddr = %s, options = %s, authLen = %d\n",
|
|||
|
hostAddress, startOptions, authLen);
|
|||
|
if (authLen > 0)
|
|||
|
printf (" authName = %s\n", authName);
|
|||
|
}
|
|||
|
|
|||
|
IceDisposeCompleteMessage (iceConn, pStart);
|
|||
|
|
|||
|
ForwardRequest (pmConn, serviceName, serverAddress, hostAddress,
|
|||
|
startOptions, authLen, authName, authData);
|
|||
|
|
|||
|
if (serviceName)
|
|||
|
free (serviceName);
|
|||
|
if (serverAddress)
|
|||
|
free (serverAddress);
|
|||
|
if (hostAddress)
|
|||
|
free (hostAddress);
|
|||
|
if (startOptions)
|
|||
|
free (startOptions);
|
|||
|
if (authName)
|
|||
|
free (authName);
|
|||
|
if (authData)
|
|||
|
free (authData);
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
case PM_StartProxy:
|
|||
|
{
|
|||
|
pmStartProxyMsg *pMsg;
|
|||
|
char *pData, *pStart;
|
|||
|
char *serviceName = NULL;
|
|||
|
char *serverAddress;
|
|||
|
char *hostAddress;
|
|||
|
char *startOptions;
|
|||
|
int authLen;
|
|||
|
char *authName;
|
|||
|
char *authData;
|
|||
|
|
|||
|
#if 0 /* No-op */
|
|||
|
CHECK_AT_LEAST_SIZE (iceConn, pmConn->pmOpcode, opcode,
|
|||
|
length, SIZEOF (pmStartProxyMsg), IceFatalToProtocol);
|
|||
|
#endif
|
|||
|
|
|||
|
IceReadCompleteMessage (iceConn, SIZEOF (pmStartProxyMsg),
|
|||
|
pmStartProxyMsg, pMsg, pStart);
|
|||
|
|
|||
|
if (!IceValidIO (iceConn))
|
|||
|
{
|
|||
|
IceDisposeCompleteMessage (iceConn, pStart);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
pData = pStart;
|
|||
|
|
|||
|
SKIP_STRING (pData, swap); /* proxy-service */
|
|||
|
|
|||
|
CHECK_COMPLETE_SIZE (iceConn, pmConn->pmOpcode, opcode,
|
|||
|
length, pData - pStart + SIZEOF (pmStartProxyMsg),
|
|||
|
pStart, IceFatalToProtocol);
|
|||
|
|
|||
|
pData = pStart;
|
|||
|
|
|||
|
EXTRACT_STRING (pData, swap, serviceName);
|
|||
|
|
|||
|
assert(serviceName);
|
|||
|
|
|||
|
if (verbose)
|
|||
|
printf ("Got StartProxy on fd %d, serviceName = %s\n",
|
|||
|
IceConnectionNumber(iceConn), serviceName);
|
|||
|
|
|||
|
IceDisposeCompleteMessage (iceConn, pStart);
|
|||
|
|
|||
|
if (! ActivateProxyService (serviceName, pmConn)) {
|
|||
|
fputs ("Configuration error: received unexpected StartProxy for service ", stderr);
|
|||
|
fputs (serviceName, stderr);
|
|||
|
fputc ('\n', stderr);
|
|||
|
IceCloseConnection (iceConn);
|
|||
|
}
|
|||
|
else {
|
|||
|
|
|||
|
/*
|
|||
|
* Now send the GetProxyAddr message to the proxy.
|
|||
|
*/
|
|||
|
if (PeekRequestorQueue(pmConn,
|
|||
|
NULL, NULL, NULL,
|
|||
|
&serverAddress, &hostAddress, &startOptions,
|
|||
|
&authLen, &authName, &authData)) {
|
|||
|
SendGetProxyAddr(pmConn,
|
|||
|
serviceName, serverAddress,
|
|||
|
hostAddress, startOptions,
|
|||
|
authLen, authName, authData);
|
|||
|
}
|
|||
|
else if (verbose) {
|
|||
|
fputs ("Received StartProxy for service ", stderr);
|
|||
|
fputs (serviceName, stderr);
|
|||
|
fputs (" but no waiting GetproxyAddr requests\n", stderr);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
free (serviceName);
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
case PM_GetProxyAddrReply:
|
|||
|
|
|||
|
{
|
|||
|
pmGetProxyAddrReplyMsg *pMsg;
|
|||
|
char *pData, *pStart;
|
|||
|
char *addr = NULL, *error = NULL;
|
|||
|
|
|||
|
#if 0 /* No-op */
|
|||
|
CHECK_AT_LEAST_SIZE (iceConn, pmConn->pmOpcode, opcode,
|
|||
|
length, SIZEOF (pmGetProxyAddrReplyMsg), IceFatalToProtocol);
|
|||
|
#endif
|
|||
|
|
|||
|
IceReadCompleteMessage (iceConn, SIZEOF (pmGetProxyAddrReplyMsg),
|
|||
|
pmGetProxyAddrReplyMsg, pMsg, pStart);
|
|||
|
|
|||
|
if (!IceValidIO (iceConn))
|
|||
|
{
|
|||
|
IceDisposeCompleteMessage (iceConn, pStart);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
pData = pStart;
|
|||
|
|
|||
|
SKIP_STRING (pData, swap); /* proxy-address */
|
|||
|
SKIP_STRING (pData, swap); /* failure-reason */
|
|||
|
|
|||
|
CHECK_COMPLETE_SIZE (iceConn, pmConn->pmOpcode, opcode,
|
|||
|
length, pData - pStart + SIZEOF (pmGetProxyAddrReplyMsg),
|
|||
|
pStart, IceFatalToProtocol);
|
|||
|
|
|||
|
pData = pStart;
|
|||
|
|
|||
|
EXTRACT_STRING (pData, swap, addr);
|
|||
|
EXTRACT_STRING (pData, swap, error);
|
|||
|
|
|||
|
if (verbose) {
|
|||
|
printf ("Got GetProxyAddrReply from proxy %d, status = %d, ",
|
|||
|
IceConnectionNumber(iceConn), pMsg->status);
|
|||
|
if (pMsg->status == PM_Success)
|
|||
|
printf ("addr = %s\n", addr);
|
|||
|
else
|
|||
|
printf ("error = %s\n", error);
|
|||
|
}
|
|||
|
|
|||
|
{ /* Ignore any unsolicited replies so we don't get further confused */
|
|||
|
running_proxy *proxy = ProxyForPMconn(pmConn);
|
|||
|
|
|||
|
if (!proxy || !proxy->requests)
|
|||
|
{
|
|||
|
if (verbose)
|
|||
|
fprintf (stderr, "Received unsolicited GetProxyAddrReply from proxy %d; ignoring it.\n",
|
|||
|
IceConnectionNumber(iceConn));
|
|||
|
|
|||
|
IceDisposeCompleteMessage (iceConn, pStart);
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
switch (pMsg->status) {
|
|||
|
|
|||
|
case PM_Success:
|
|||
|
{
|
|||
|
/*
|
|||
|
* Now send the GetProxyAddr reply to xfindproxy.
|
|||
|
*/
|
|||
|
|
|||
|
SendGetProxyAddrReply (
|
|||
|
PopRequestorQueue (pmConn, True, True /* free proxy list */),
|
|||
|
PM_Success /* status */, addr, NULL);
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
case PM_Unable:
|
|||
|
{
|
|||
|
running_proxy_list *proxyList;
|
|||
|
char *serviceName, *serverAddress, *hostAddress, *startOptions;
|
|||
|
PMconn *requestor;
|
|||
|
int authLen;
|
|||
|
char *authName;
|
|||
|
char *authData;
|
|||
|
|
|||
|
{
|
|||
|
running_proxy *proxy = ProxyForPMconn(pmConn);
|
|||
|
if (proxy)
|
|||
|
proxy->refused_service = True;
|
|||
|
else
|
|||
|
fputs("Internal error: received GetProxyAddrReply from an unknown proxy\n", stderr);
|
|||
|
}
|
|||
|
|
|||
|
if (! PeekRequestorQueue (pmConn, &requestor,
|
|||
|
&proxyList, &serviceName, &serverAddress,
|
|||
|
&hostAddress, &startOptions,
|
|||
|
&authLen, &authName, &authData)) {
|
|||
|
if (verbose)
|
|||
|
fputs("Received GetProxyAddrReply from a proxy with no requests\n", stderr);
|
|||
|
|
|||
|
proxyList = NULL;
|
|||
|
serviceName = "?unknown service--internal error";
|
|||
|
}
|
|||
|
|
|||
|
if (proxyList && (proxyList->current < proxyList->count - 1))
|
|||
|
{
|
|||
|
/*
|
|||
|
* Ask the next running proxy if it can service this request.
|
|||
|
*/
|
|||
|
running_proxy *nextProxy;
|
|||
|
|
|||
|
proxyList->current++;
|
|||
|
nextProxy = proxyList->list[proxyList->current];
|
|||
|
|
|||
|
if (nextProxy->pmConn != NULL) {
|
|||
|
/* send only if the proxy has started */
|
|||
|
SendGetProxyAddr (nextProxy->pmConn, serviceName,
|
|||
|
serverAddress, hostAddress, startOptions,
|
|||
|
authLen, authName, authData);
|
|||
|
}
|
|||
|
|
|||
|
PushRequestorQueue (nextProxy, requestor, proxyList,
|
|||
|
serviceName, serverAddress, hostAddress, startOptions,
|
|||
|
authLen, authName, authData);
|
|||
|
|
|||
|
PopRequestorQueue (pmConn, False, False);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
/*
|
|||
|
* Start a new proxy.
|
|||
|
*/
|
|||
|
|
|||
|
running_proxy *runningProxy = NULL;
|
|||
|
char *startCommand;
|
|||
|
char *proxyAddress;
|
|||
|
Bool managed;
|
|||
|
|
|||
|
if (!GetConfig (configFile, serviceName, &managed,
|
|||
|
&startCommand, &proxyAddress))
|
|||
|
{
|
|||
|
SendGetProxyAddrReply (requestor, PM_Failure,
|
|||
|
NULL, "Could not read proxy manager config file");
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
runningProxy = StartNewProxy (serviceName, startCommand);
|
|||
|
|
|||
|
if (runningProxy)
|
|||
|
{
|
|||
|
PushRequestorQueue (runningProxy,
|
|||
|
requestor, proxyList,
|
|||
|
serviceName, serverAddress,
|
|||
|
hostAddress, startOptions,
|
|||
|
authLen, authName, authData);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
SendGetProxyAddrReply (pmConn, PM_Failure,
|
|||
|
NULL, "Can't start new proxy");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (startCommand)
|
|||
|
free (startCommand);
|
|||
|
if (proxyAddress)
|
|||
|
free (proxyAddress);
|
|||
|
|
|||
|
PopRequestorQueue (pmConn, False,
|
|||
|
runningProxy ? False : True /* free proxy list */);
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
default:
|
|||
|
if (verbose && pMsg->status != PM_Unable)
|
|||
|
fprintf(stderr,
|
|||
|
"Error: proxy returned unrecognized status: %d\n",
|
|||
|
pMsg->status);
|
|||
|
/* FALLTHROUGH */
|
|||
|
|
|||
|
case PM_Failure:
|
|||
|
SendGetProxyAddrReply (
|
|||
|
PopRequestorQueue (pmConn, True, True /* free proxy list */),
|
|||
|
pMsg->status, NULL, error);
|
|||
|
}
|
|||
|
|
|||
|
IceDisposeCompleteMessage (iceConn, pStart);
|
|||
|
|
|||
|
/* see if there was more work queued for this proxy */
|
|||
|
{
|
|||
|
char *serviceName, *serverAddress, *hostAddress, *startOptions;
|
|||
|
int authLen;
|
|||
|
char *authName, *authData;
|
|||
|
|
|||
|
if (PeekRequestorQueue(pmConn,
|
|||
|
NULL, NULL, &serviceName,
|
|||
|
&serverAddress, &hostAddress, &startOptions,
|
|||
|
&authLen, &authName, &authData)) {
|
|||
|
SendGetProxyAddr(pmConn,
|
|||
|
serviceName, serverAddress,
|
|||
|
hostAddress, startOptions,
|
|||
|
authLen, authName, authData);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (addr)
|
|||
|
free (addr);
|
|||
|
if (error)
|
|||
|
free (error);
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
case PM_Error:
|
|||
|
{
|
|||
|
iceErrorMsg *pMsg;
|
|||
|
char *pStart;
|
|||
|
|
|||
|
CHECK_AT_LEAST_SIZE (iceConn, pmConn->pmOpcode, PM_Error, length,
|
|||
|
sizeof(iceErrorMsg), IceFatalToProtocol);
|
|||
|
|
|||
|
IceReadCompleteMessage (iceConn, SIZEOF (iceErrorMsg),
|
|||
|
iceErrorMsg, pMsg, pStart);
|
|||
|
|
|||
|
if (!IceValidIO (iceConn))
|
|||
|
{
|
|||
|
IceDisposeCompleteMessage (iceConn, pStart);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if (swap)
|
|||
|
{
|
|||
|
pMsg->errorClass = lswaps (pMsg->errorClass);
|
|||
|
pMsg->offendingSequenceNum = lswapl (pMsg->offendingSequenceNum);
|
|||
|
}
|
|||
|
|
|||
|
fprintf(stderr, "Received ICE Error: class=0x%x\n offending minor opcode=%d, severity=%d, sequence=%d\n",
|
|||
|
pMsg->errorClass, pMsg->offendingMinorOpcode, pMsg->severity,
|
|||
|
(int)pMsg->offendingSequenceNum);
|
|||
|
|
|||
|
IceDisposeCompleteMessage (iceConn, pStart);
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
default:
|
|||
|
{
|
|||
|
_IceErrorBadMinor (iceConn, pmConn->pmOpcode, opcode, IceCanContinue);
|
|||
|
_IceReadSkip (iceConn, length << 3);
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
PMSetupProcessMessages (iceConn, clientData, opcode, length, swap,
|
|||
|
replyWait, replyReadyRet)
|
|||
|
|
|||
|
IceConn iceConn;
|
|||
|
IcePointer clientData;
|
|||
|
int opcode;
|
|||
|
unsigned long length;
|
|||
|
Bool swap;
|
|||
|
IceReplyWaitInfo *replyWait;
|
|||
|
Bool *replyReadyRet;
|
|||
|
|
|||
|
{
|
|||
|
assert (replyWait == NULL);
|
|||
|
|
|||
|
PMReplyProcessMessages (iceConn, clientData, opcode, length, swap);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
void
|
|||
|
ForwardRequest( requestor, serviceName, serverAddress, hostAddress,
|
|||
|
startOptions, authLen, authName, authData )
|
|||
|
PMconn *requestor;
|
|||
|
char *serviceName, *serverAddress, *hostAddress, *startOptions;
|
|||
|
int authLen;
|
|||
|
char *authName, *authData;
|
|||
|
{
|
|||
|
running_proxy_list *proxyList;
|
|||
|
running_proxy *runningProxy = NULL;
|
|||
|
int pushRequest = 0;
|
|||
|
|
|||
|
if ((proxyList = GetRunningProxyList (
|
|||
|
serviceName, serverAddress)) != NULL)
|
|||
|
{
|
|||
|
while (proxyList->current < proxyList->count) {
|
|||
|
runningProxy = proxyList->list[proxyList->current];
|
|||
|
|
|||
|
if (runningProxy->pmConn != NULL) {
|
|||
|
SendGetProxyAddr (runningProxy->pmConn, serviceName,
|
|||
|
serverAddress, hostAddress, NULL,
|
|||
|
authLen, authName, authData);
|
|||
|
break;
|
|||
|
}
|
|||
|
proxyList->current++;
|
|||
|
}
|
|||
|
|
|||
|
pushRequest = 1;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
Bool managed;
|
|||
|
char *startCommand;
|
|||
|
char *proxyAddress;
|
|||
|
|
|||
|
if (!GetConfig (configFile, serviceName, &managed,
|
|||
|
&startCommand, &proxyAddress))
|
|||
|
{
|
|||
|
SendGetProxyAddrReply (requestor, PM_Failure,
|
|||
|
NULL, "Could not find requested service");
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if (managed)
|
|||
|
{
|
|||
|
runningProxy = StartNewProxy (serviceName, startCommand);
|
|||
|
|
|||
|
if (runningProxy)
|
|||
|
pushRequest = 1;
|
|||
|
else
|
|||
|
{
|
|||
|
SendGetProxyAddrReply (requestor, PM_Failure,
|
|||
|
NULL, "Can't start new proxy");
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
/*
|
|||
|
* We have the unmanged proxy's address; now forward
|
|||
|
* the request to it.
|
|||
|
*/
|
|||
|
|
|||
|
runningProxy = ConnectToProxy (PMOriginatorOpcode,
|
|||
|
serviceName, proxyAddress);
|
|||
|
|
|||
|
if (runningProxy) {
|
|||
|
SendGetProxyAddr (runningProxy->pmConn,
|
|||
|
serviceName, serverAddress,
|
|||
|
hostAddress, startOptions,
|
|||
|
authLen, authName, authData);
|
|||
|
pushRequest = 1;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
/* %%% We should reread the config file and look
|
|||
|
* for another proxy address before giving up.
|
|||
|
*/
|
|||
|
SendGetProxyAddrReply (requestor, PM_Failure,
|
|||
|
NULL, "Can't connect to proxy");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (startCommand)
|
|||
|
free (startCommand);
|
|||
|
if (proxyAddress)
|
|||
|
free (proxyAddress);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (pushRequest)
|
|||
|
{
|
|||
|
PushRequestorQueue (runningProxy, requestor, proxyList,
|
|||
|
serviceName, serverAddress, hostAddress, startOptions,
|
|||
|
authLen, authName, authData);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/* ARGSUSED */
|
|||
|
void
|
|||
|
_XtProcessIceMsgProc (client_data, source, id)
|
|||
|
|
|||
|
XtPointer client_data;
|
|||
|
int *source;
|
|||
|
XtInputId *id;
|
|||
|
|
|||
|
{
|
|||
|
IceConn ice_conn = (IceConn) client_data;
|
|||
|
IceProcessMessagesStatus status;
|
|||
|
|
|||
|
status = IceProcessMessages (ice_conn, NULL, NULL);
|
|||
|
|
|||
|
if (status == IceProcessMessagesIOError)
|
|||
|
{
|
|||
|
Bool activeReqs;
|
|||
|
|
|||
|
ProxyGone (ice_conn, &activeReqs);
|
|||
|
IceSetShutdownNegotiation (ice_conn, False);
|
|||
|
IceCloseConnection (ice_conn);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
void
|
|||
|
_XtIceWatchProc (ice_conn, client_data, opening, watch_data)
|
|||
|
|
|||
|
IceConn ice_conn;
|
|||
|
IcePointer client_data;
|
|||
|
Bool opening;
|
|||
|
IcePointer *watch_data;
|
|||
|
|
|||
|
{
|
|||
|
if (opening)
|
|||
|
{
|
|||
|
XtAppContext appContext = (XtAppContext) client_data;
|
|||
|
|
|||
|
*watch_data = (IcePointer) XtAppAddInput (
|
|||
|
appContext,
|
|||
|
IceConnectionNumber (ice_conn),
|
|||
|
(XtPointer) XtInputReadMask,
|
|||
|
_XtProcessIceMsgProc,
|
|||
|
(XtPointer) ice_conn);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
XtRemoveInput ((XtInputId) *watch_data);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
Status
|
|||
|
InitWatchProcs (appContext)
|
|||
|
|
|||
|
XtAppContext appContext;
|
|||
|
|
|||
|
{
|
|||
|
return (IceAddConnectionWatch (_XtIceWatchProc, (IcePointer) appContext));
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
* The real way to handle IO errors is to check the return status
|
|||
|
* of IceProcessMessages. xsm properly does this.
|
|||
|
*
|
|||
|
* Unfortunately, a design flaw exists in the ICE library in which
|
|||
|
* a default IO error handler is invoked if no IO error handler is
|
|||
|
* installed. This default handler exits. We must avoid this.
|
|||
|
*
|
|||
|
* To get around this problem, we install an IO error handler that
|
|||
|
* does a little magic. Since a previous IO handler might have been
|
|||
|
* installed, when we install our IO error handler, we do a little
|
|||
|
* trick to get both the previous IO error handler and the default
|
|||
|
* IO error handler. When our IO error handler is called, if the
|
|||
|
* previous handler is not the default handler, we call it. This
|
|||
|
* way, everyone's IO error handler gets called except the stupid
|
|||
|
* default one which does an exit!
|
|||
|
*/
|
|||
|
|
|||
|
static IceIOErrorHandler prev_handler;
|
|||
|
|
|||
|
void
|
|||
|
MyIoErrorHandler (ice_conn)
|
|||
|
|
|||
|
IceConn ice_conn;
|
|||
|
|
|||
|
{
|
|||
|
if (prev_handler)
|
|||
|
(*prev_handler) (ice_conn);
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
InstallIOErrorHandler ()
|
|||
|
|
|||
|
{
|
|||
|
IceIOErrorHandler default_handler;
|
|||
|
|
|||
|
prev_handler = IceSetIOErrorHandler (NULL);
|
|||
|
default_handler = IceSetIOErrorHandler (MyIoErrorHandler);
|
|||
|
if (prev_handler == default_handler)
|
|||
|
prev_handler = NULL;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
* Since proxy manager does not authenticate connections, we disable
|
|||
|
* authentication by always returning true in the host based auth proc.
|
|||
|
*/
|
|||
|
|
|||
|
Bool
|
|||
|
HostBasedAuthProc (hostname)
|
|||
|
|
|||
|
char *hostname;
|
|||
|
|
|||
|
{
|
|||
|
return (1);
|
|||
|
}
|