2010-12-01 16:36:40 +00:00
|
|
|
/*
|
|
|
|
* virnetserverservice.c: generic network RPC server service
|
|
|
|
*
|
|
|
|
* Copyright (C) 2006-2011 Red Hat, Inc.
|
|
|
|
* Copyright (C) 2006 Daniel P. Berrange
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*
|
|
|
|
* Author: Daniel P. Berrange <berrange@redhat.com>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include "virnetserverservice.h"
|
|
|
|
|
|
|
|
#include "memory.h"
|
|
|
|
#include "virterror_internal.h"
|
|
|
|
|
|
|
|
|
|
|
|
#define VIR_FROM_THIS VIR_FROM_RPC
|
|
|
|
|
|
|
|
struct _virNetServerService {
|
|
|
|
int refs;
|
|
|
|
|
|
|
|
size_t nsocks;
|
|
|
|
virNetSocketPtr *socks;
|
|
|
|
|
|
|
|
int auth;
|
|
|
|
bool readonly;
|
2011-06-30 10:45:55 +00:00
|
|
|
size_t nrequests_client_max;
|
2010-12-01 16:36:40 +00:00
|
|
|
|
|
|
|
virNetTLSContextPtr tls;
|
|
|
|
|
|
|
|
virNetServerServiceDispatchFunc dispatchFunc;
|
|
|
|
void *dispatchOpaque;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void virNetServerServiceAccept(virNetSocketPtr sock,
|
|
|
|
int events ATTRIBUTE_UNUSED,
|
|
|
|
void *opaque)
|
|
|
|
{
|
|
|
|
virNetServerServicePtr svc = opaque;
|
|
|
|
virNetServerClientPtr client = NULL;
|
|
|
|
virNetSocketPtr clientsock = NULL;
|
|
|
|
|
|
|
|
if (virNetSocketAccept(sock, &clientsock) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (!clientsock) /* Connection already went away */
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!(client = virNetServerClientNew(clientsock,
|
|
|
|
svc->auth,
|
|
|
|
svc->readonly,
|
2011-06-30 10:45:55 +00:00
|
|
|
svc->nrequests_client_max,
|
2010-12-01 16:36:40 +00:00
|
|
|
svc->tls)))
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (!svc->dispatchFunc)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (svc->dispatchFunc(svc, client, svc->dispatchOpaque) < 0)
|
|
|
|
virNetServerClientClose(client);
|
|
|
|
|
|
|
|
virNetServerClientFree(client);
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
return;
|
|
|
|
|
|
|
|
error:
|
2011-07-04 02:22:50 +00:00
|
|
|
if (client) {
|
|
|
|
virNetServerClientClose(client);
|
|
|
|
virNetServerClientFree(client);
|
|
|
|
} else {
|
|
|
|
virNetSocketFree(clientsock);
|
|
|
|
}
|
2010-12-01 16:36:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-07-19 13:11:33 +00:00
|
|
|
static void virNetServerServiceEventFree(void *opaque)
|
|
|
|
{
|
|
|
|
virNetServerServicePtr svc = opaque;
|
|
|
|
|
|
|
|
virNetServerServiceFree(svc);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-12-01 16:36:40 +00:00
|
|
|
virNetServerServicePtr virNetServerServiceNewTCP(const char *nodename,
|
|
|
|
const char *service,
|
|
|
|
int auth,
|
|
|
|
bool readonly,
|
2011-06-30 10:45:55 +00:00
|
|
|
size_t nrequests_client_max,
|
2010-12-01 16:36:40 +00:00
|
|
|
virNetTLSContextPtr tls)
|
|
|
|
{
|
|
|
|
virNetServerServicePtr svc;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
if (VIR_ALLOC(svc) < 0)
|
|
|
|
goto no_memory;
|
|
|
|
|
|
|
|
svc->refs = 1;
|
|
|
|
svc->auth = auth;
|
|
|
|
svc->readonly = readonly;
|
2011-06-30 10:45:55 +00:00
|
|
|
svc->nrequests_client_max = nrequests_client_max;
|
2010-12-01 16:36:40 +00:00
|
|
|
svc->tls = tls;
|
|
|
|
if (tls)
|
|
|
|
virNetTLSContextRef(tls);
|
|
|
|
|
|
|
|
if (virNetSocketNewListenTCP(nodename,
|
|
|
|
service,
|
|
|
|
&svc->socks,
|
|
|
|
&svc->nsocks) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
for (i = 0 ; i < svc->nsocks ; i++) {
|
|
|
|
if (virNetSocketListen(svc->socks[i]) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
/* IO callback is initially disabled, until we're ready
|
|
|
|
* to deal with incoming clients */
|
2011-07-19 13:11:33 +00:00
|
|
|
virNetServerServiceRef(svc);
|
2010-12-01 16:36:40 +00:00
|
|
|
if (virNetSocketAddIOCallback(svc->socks[i],
|
|
|
|
0,
|
|
|
|
virNetServerServiceAccept,
|
2011-07-19 13:11:33 +00:00
|
|
|
svc,
|
|
|
|
virNetServerServiceEventFree) < 0) {
|
|
|
|
virNetServerServiceFree(svc);
|
2010-12-01 16:36:40 +00:00
|
|
|
goto error;
|
2011-07-19 13:11:33 +00:00
|
|
|
}
|
2010-12-01 16:36:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return svc;
|
|
|
|
|
|
|
|
no_memory:
|
|
|
|
virReportOOMError();
|
|
|
|
error:
|
|
|
|
virNetServerServiceFree(svc);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
virNetServerServicePtr virNetServerServiceNewUNIX(const char *path,
|
|
|
|
mode_t mask,
|
|
|
|
gid_t grp,
|
|
|
|
int auth,
|
|
|
|
bool readonly,
|
2011-06-30 10:45:55 +00:00
|
|
|
size_t nrequests_client_max,
|
2010-12-01 16:36:40 +00:00
|
|
|
virNetTLSContextPtr tls)
|
|
|
|
{
|
|
|
|
virNetServerServicePtr svc;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (VIR_ALLOC(svc) < 0)
|
|
|
|
goto no_memory;
|
|
|
|
|
|
|
|
svc->refs = 1;
|
|
|
|
svc->auth = auth;
|
|
|
|
svc->readonly = readonly;
|
2011-06-30 10:45:55 +00:00
|
|
|
svc->nrequests_client_max = nrequests_client_max;
|
2010-12-01 16:36:40 +00:00
|
|
|
svc->tls = tls;
|
|
|
|
if (tls)
|
|
|
|
virNetTLSContextRef(tls);
|
|
|
|
|
|
|
|
svc->nsocks = 1;
|
|
|
|
if (VIR_ALLOC_N(svc->socks, svc->nsocks) < 0)
|
|
|
|
goto no_memory;
|
|
|
|
|
|
|
|
if (virNetSocketNewListenUNIX(path,
|
|
|
|
mask,
|
|
|
|
grp,
|
|
|
|
&svc->socks[0]) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
for (i = 0 ; i < svc->nsocks ; i++) {
|
|
|
|
if (virNetSocketListen(svc->socks[i]) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
/* IO callback is initially disabled, until we're ready
|
|
|
|
* to deal with incoming clients */
|
2011-07-19 13:11:33 +00:00
|
|
|
virNetServerServiceRef(svc);
|
2010-12-01 16:36:40 +00:00
|
|
|
if (virNetSocketAddIOCallback(svc->socks[i],
|
|
|
|
0,
|
|
|
|
virNetServerServiceAccept,
|
2011-07-19 13:11:33 +00:00
|
|
|
svc,
|
|
|
|
virNetServerServiceEventFree) < 0) {
|
|
|
|
virNetServerServiceFree(svc);
|
2010-12-01 16:36:40 +00:00
|
|
|
goto error;
|
2011-07-19 13:11:33 +00:00
|
|
|
}
|
2010-12-01 16:36:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return svc;
|
|
|
|
|
|
|
|
no_memory:
|
|
|
|
virReportOOMError();
|
|
|
|
error:
|
|
|
|
virNetServerServiceFree(svc);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-03-02 17:11:42 +00:00
|
|
|
int virNetServerServiceGetPort(virNetServerServicePtr svc)
|
|
|
|
{
|
|
|
|
/* We're assuming if there are multiple sockets
|
|
|
|
* for IPv4 & 6, then they are all on same port */
|
|
|
|
return virNetSocketGetPort(svc->socks[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-12-01 16:36:40 +00:00
|
|
|
int virNetServerServiceGetAuth(virNetServerServicePtr svc)
|
|
|
|
{
|
|
|
|
return svc->auth;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool virNetServerServiceIsReadonly(virNetServerServicePtr svc)
|
|
|
|
{
|
|
|
|
return svc->readonly;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void virNetServerServiceRef(virNetServerServicePtr svc)
|
|
|
|
{
|
|
|
|
svc->refs++;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void virNetServerServiceSetDispatcher(virNetServerServicePtr svc,
|
|
|
|
virNetServerServiceDispatchFunc func,
|
|
|
|
void *opaque)
|
|
|
|
{
|
|
|
|
svc->dispatchFunc = func;
|
|
|
|
svc->dispatchOpaque = opaque;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void virNetServerServiceFree(virNetServerServicePtr svc)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (!svc)
|
|
|
|
return;
|
|
|
|
|
|
|
|
svc->refs--;
|
|
|
|
if (svc->refs > 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (i = 0 ; i < svc->nsocks ; i++)
|
|
|
|
virNetSocketFree(svc->socks[i]);
|
|
|
|
VIR_FREE(svc->socks);
|
|
|
|
|
|
|
|
virNetTLSContextFree(svc->tls);
|
|
|
|
|
|
|
|
VIR_FREE(svc);
|
|
|
|
}
|
|
|
|
|
|
|
|
void virNetServerServiceToggle(virNetServerServicePtr svc,
|
|
|
|
bool enabled)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0 ; i < svc->nsocks ; i++)
|
|
|
|
virNetSocketUpdateIOCallback(svc->socks[i],
|
|
|
|
enabled ?
|
|
|
|
VIR_EVENT_HANDLE_READABLE :
|
|
|
|
0);
|
|
|
|
}
|