2006-06-28 18:19:13 +00:00
/*
* proxy_svr . c : root suid proxy server for Xen access to APIs with no
* side effects from unauthenticated clients .
*
* Copyright ( C ) 2006 Red Hat , Inc .
*
* See COPYING . LIB for the License of this software
*
* Daniel Veillard < veillard @ redhat . com >
*/
# include <stdio.h>
# include <stdlib.h>
# include <unistd.h>
# include <errno.h>
# include <sys/types.h>
# include <sys/poll.h>
# include <sys/socket.h>
# include <sys/un.h>
2007-03-01 16:01:39 +00:00
# include <locale.h>
2006-06-28 18:19:13 +00:00
# include "internal.h"
2007-03-15 07:43:16 +00:00
# ifdef WITH_XEN
2006-06-29 22:12:47 +00:00
# include "proxy_internal.h"
2006-06-28 18:19:13 +00:00
# include "xen_internal.h"
2006-06-29 14:44:37 +00:00
# include "xend_internal.h"
2006-08-09 15:21:16 +00:00
# include "xs_internal.h"
2007-04-04 14:19:49 +00:00
# include "xen_unified.h"
2006-06-28 18:19:13 +00:00
static int fdServer = - 1 ;
static int debug = 0 ;
2006-06-29 14:44:37 +00:00
static int persist = 0 ;
2006-06-28 18:19:13 +00:00
static int done = 0 ;
# define MAX_CLIENT 64
static int nbClients = 0 ; /* client 0 is the unix listen socket */
static struct pollfd pollInfos [ MAX_CLIENT + 1 ] ;
static virConnect conninfos ;
static virConnectPtr conn = & conninfos ;
2006-06-29 14:44:37 +00:00
static unsigned long xenVersion = 0 ;
2006-06-28 18:19:13 +00:00
/************************************************************************
* *
* Interfaces with the Xen hypervisor *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
* proxyInitXen :
*
* Initialize the communication layer with Xen
*
* Returns 0 or - 1 in case of error
*/
static int
proxyInitXen ( void ) {
int ret ;
2006-06-29 14:44:37 +00:00
unsigned long xenVersion2 ;
2007-04-04 14:19:49 +00:00
xenUnifiedPrivatePtr priv ;
/* Allocate per-connection private data. */
priv = malloc ( sizeof * priv ) ;
if ( ! priv ) {
fprintf ( stderr , " Failed to allocate private data \n " ) ;
return ( - 1 ) ;
}
conn - > privateData = priv ;
priv - > handle = - 1 ;
priv - > xendConfigVersion = - 1 ;
priv - > type = - 1 ;
priv - > len = - 1 ;
priv - > addr = NULL ;
priv - > xshandle = NULL ;
priv - > proxy = - 1 ;
2006-06-28 18:19:13 +00:00
2007-04-30 17:30:11 +00:00
ret = xenHypervisorOpen ( conn , NULL , 0 ) ;
2006-06-28 18:19:13 +00:00
if ( ret < 0 ) {
fprintf ( stderr , " Failed to open Xen hypervisor \n " ) ;
return ( - 1 ) ;
2006-06-29 14:44:37 +00:00
} else {
ret = xenHypervisorGetVersion ( conn , & xenVersion ) ;
if ( ret ! = 0 ) {
fprintf ( stderr , " Failed to get Xen hypervisor version \n " ) ;
return ( - 1 ) ;
}
2006-06-28 18:19:13 +00:00
}
ret = xenDaemonOpen_unix ( conn , " /var/lib/xend/xend-socket " ) ;
if ( ret < 0 ) {
fprintf ( stderr , " Failed to connect to Xen daemon \n " ) ;
return ( - 1 ) ;
}
2007-04-30 17:30:11 +00:00
ret = xenStoreOpen ( conn , NULL , VIR_DRV_OPEN_RO ) ;
2006-08-09 15:21:16 +00:00
if ( ret < 0 ) {
fprintf ( stderr , " Failed to open XenStore connection " ) ;
return ( - 1 ) ;
}
2006-06-29 14:44:37 +00:00
ret = xenDaemonGetVersion ( conn , & xenVersion2 ) ;
if ( ret ! = 0 ) {
fprintf ( stderr , " Failed to get Xen daemon version \n " ) ;
return ( - 1 ) ;
}
if ( debug )
fprintf ( stderr , " Connected to hypervisor %lu and daemon %lu \n " ,
xenVersion , xenVersion2 ) ;
if ( xenVersion2 > xenVersion )
xenVersion = xenVersion2 ;
2006-06-28 18:19:13 +00:00
return ( 0 ) ;
}
/************************************************************************
* *
* Processing of the unix socket to listen for clients *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
* proxyCloseUnixSocket :
*
* close the unix socket
*
* Returns 0 or - 1 in case of error
*/
static int
proxyCloseUnixSocket ( void ) {
int ret ;
if ( fdServer < 0 )
return ( 0 ) ;
ret = close ( fdServer ) ;
if ( debug > 0 )
fprintf ( stderr , " closing unix socket %d: %d \n " , fdServer , ret ) ;
fdServer = - 1 ;
pollInfos [ 0 ] . fd = - 1 ;
return ( ret ) ;
}
/**
* proxyListenUnixSocket :
* @ path : the fileame for the socket
*
* create a new abstract socket based on that path and listen on it
*
* Returns the associated file descriptor or - 1 in case of failure
*/
static int
proxyListenUnixSocket ( const char * path ) {
int fd ;
struct sockaddr_un addr ;
if ( fdServer > = 0 )
return ( fdServer ) ;
fd = socket ( PF_UNIX , SOCK_STREAM , 0 ) ;
if ( fd < 0 ) {
fprintf ( stderr , " Failed to create unix socket " ) ;
return ( - 1 ) ;
}
/*
* Abstract socket do not hit the filesystem , way more secure and
* garanteed to be atomic
*/
memset ( & addr , 0 , sizeof ( addr ) ) ;
addr . sun_family = AF_UNIX ;
addr . sun_path [ 0 ] = ' \0 ' ;
strncpy ( & addr . sun_path [ 1 ] , path , ( sizeof ( addr ) - 4 ) - 2 ) ;
/*
* now bind the socket to that address and listen on it
*/
if ( bind ( fd , ( struct sockaddr * ) & addr , sizeof ( addr ) ) < 0 ) {
fprintf ( stderr , " Failed to bind to socket %s \n " , path ) ;
close ( fd ) ;
return ( - 1 ) ;
}
if ( listen ( fd , 30 /* backlog */ ) < 0 ) {
fprintf ( stderr , " Failed to listen to socket %s \n " , path ) ;
close ( fd ) ;
return ( - 1 ) ;
}
if ( debug > 0 )
fprintf ( stderr , " opened and bound unix socket %d \n " , fd ) ;
fdServer = fd ;
pollInfos [ 0 ] . fd = fd ;
pollInfos [ 0 ] . events = POLLIN | POLLERR | POLLHUP | POLLNVAL ;
return ( fd ) ;
}
/**
* proxyAcceptClientSocket :
*
* Process a request to the unix socket
*
* Returns the filedescriptor of the new client or - 1 in case of error
*/
static int
proxyAcceptClientSocket ( void ) {
int client ;
socklen_t client_addrlen ;
struct sockaddr client_addr ;
retry :
client_addrlen = sizeof ( client_addr ) ;
client = accept ( pollInfos [ 0 ] . fd , & client_addr , & client_addrlen ) ;
if ( client < 0 ) {
if ( errno = = EINTR ) {
if ( debug > 0 )
fprintf ( stderr , " accept connection on socket %d interrupted \n " ,
pollInfos [ 0 ] . fd ) ;
goto retry ;
}
fprintf ( stderr , " Failed to accept incoming connection on socket %d \n " ,
pollInfos [ 0 ] . fd ) ;
done = 1 ;
return ( - 1 ) ;
}
if ( nbClients > = MAX_CLIENT ) {
fprintf ( stderr , " Too many client registered \n " ) ;
close ( client ) ;
return ( - 1 ) ;
}
nbClients + + ;
pollInfos [ nbClients ] . fd = client ;
pollInfos [ nbClients ] . events = POLLIN | POLLERR | POLLHUP | POLLNVAL ;
if ( debug > 0 )
fprintf ( stderr , " accept connection on socket %d for client %d \n " ,
client , nbClients ) ;
return ( client ) ;
}
/************************************************************************
* *
* Processing of client sockets *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
* proxyCloseClientSocket :
* @ nr : client number
*
* Close the socket from that client , and recompact the pollInfo array
*
* Returns 0 in case of success and - 1 in case of error
*/
static int
proxyCloseClientSocket ( int nr ) {
int ret ;
ret = close ( pollInfos [ nr ] . fd ) ;
if ( ret ! = 0 )
fprintf ( stderr , " Failed to close socket %d from client %d \n " ,
pollInfos [ nr ] . fd , nr ) ;
else if ( debug > 0 )
fprintf ( stderr , " Closed socket %d from client %d \n " ,
pollInfos [ nr ] . fd , nr ) ;
if ( nr < nbClients ) {
memmove ( & pollInfos [ nr ] , & pollInfos [ nr + 1 ] ,
( nbClients - nr ) * sizeof ( pollInfos [ 0 ] ) ) ;
}
nbClients - - ;
return ( ret ) ;
}
/**
* proxyCloseClientSockets :
*
* Close all the sockets from the clients
*/
static void
proxyCloseClientSockets ( void ) {
int i , ret ;
for ( i = 1 ; i < = nbClients ; i + + ) {
ret = close ( pollInfos [ i ] . fd ) ;
if ( ret ! = 0 )
fprintf ( stderr , " Failed to close socket %d from client %d \n " ,
pollInfos [ i ] . fd , i ) ;
else if ( debug > 0 )
fprintf ( stderr , " Closed socket %d from client %d \n " ,
pollInfos [ i ] . fd , i ) ;
}
nbClients = 0 ;
}
/**
* proxyWriteClientSocket :
* @ nr : the client number
* @ req : pointer to the packet
*
* Send back a packet to the client . If it seems write would be blocking
* then try to disconnect from it .
*
* Return 0 in case of success and - 1 in case of error .
*/
static int
proxyWriteClientSocket ( int nr , virProxyPacketPtr req ) {
int ret ;
if ( ( nr < = 0 ) | | ( nr > nbClients ) | | ( req = = NULL ) | |
2006-06-29 22:12:47 +00:00
( req - > len < sizeof ( virProxyPacket ) ) | |
( req - > len > sizeof ( virProxyFullPacket ) ) | |
2006-06-28 18:19:13 +00:00
( pollInfos [ nr ] . fd < 0 ) ) {
fprintf ( stderr , " write to client %d in error " , nr ) ;
proxyCloseClientSocket ( nr ) ;
return ( - 1 ) ;
}
retry :
ret = write ( pollInfos [ nr ] . fd , ( char * ) req , req - > len ) ;
if ( ret < 0 ) {
if ( errno = = EINTR ) {
if ( debug > 0 )
fprintf ( stderr , " write socket %d to client %d interrupted \n " ,
pollInfos [ nr ] . fd , nr ) ;
goto retry ;
}
fprintf ( stderr , " write %d bytes to socket %d from client %d failed \n " ,
req - > len , pollInfos [ nr ] . fd , nr ) ;
proxyCloseClientSocket ( nr ) ;
return ( - 1 ) ;
}
if ( ret = = 0 ) {
if ( debug )
fprintf ( stderr , " end of stream from client %d on socket %d \n " ,
nr , pollInfos [ nr ] . fd ) ;
proxyCloseClientSocket ( nr ) ;
return ( - 1 ) ;
}
if ( ret ! = req - > len ) {
fprintf ( stderr , " write %d of %d bytes to socket %d from client %d \n " ,
ret , req - > len , pollInfos [ nr ] . fd , nr ) ;
proxyCloseClientSocket ( nr ) ;
return ( - 1 ) ;
}
if ( debug )
fprintf ( stderr , " wrote %d bytes to client %d on socket %d \n " ,
ret , nr , pollInfos [ nr ] . fd ) ;
return ( 0 ) ;
}
/**
* proxyReadClientSocket :
* @ nr : the client number
*
* Process a read from a client socket
*/
static int
proxyReadClientSocket ( int nr ) {
2006-06-29 22:12:47 +00:00
virProxyFullPacket request ;
virProxyPacketPtr req = ( virProxyPacketPtr ) & request ;
2006-06-28 18:19:13 +00:00
int ret ;
2006-11-07 16:28:16 +00:00
char * xml , * ostype ;
2006-06-28 18:19:13 +00:00
retry :
2006-06-29 22:12:47 +00:00
ret = read ( pollInfos [ nr ] . fd , req , sizeof ( virProxyPacket ) ) ;
2006-06-28 18:19:13 +00:00
if ( ret < 0 ) {
if ( errno = = EINTR ) {
if ( debug > 0 )
fprintf ( stderr , " read socket %d from client %d interrupted \n " ,
pollInfos [ nr ] . fd , nr ) ;
goto retry ;
}
fprintf ( stderr , " Failed to read socket %d from client %d \n " ,
pollInfos [ nr ] . fd , nr ) ;
proxyCloseClientSocket ( nr ) ;
return ( - 1 ) ;
}
if ( ret = = 0 ) {
if ( debug )
fprintf ( stderr , " end of stream from client %d on socket %d \n " ,
nr , pollInfos [ nr ] . fd ) ;
proxyCloseClientSocket ( nr ) ;
return ( - 1 ) ;
}
if ( debug )
fprintf ( stderr , " read %d bytes from client %d on socket %d \n " ,
ret , nr , pollInfos [ nr ] . fd ) ;
if ( ( req - > version ! = PROXY_PROTO_VERSION ) | |
2006-06-30 16:23:16 +00:00
( req - > len < sizeof ( virProxyPacket ) ) | |
( req - > len > sizeof ( virProxyFullPacket ) ) )
2006-06-28 18:19:13 +00:00
goto comm_error ;
2006-06-30 16:23:16 +00:00
2006-06-28 18:19:13 +00:00
if ( debug )
2006-06-29 14:44:37 +00:00
fprintf ( stderr , " Got command %d from client %d \n " , req - > command , nr ) ;
2006-06-28 18:19:13 +00:00
2006-06-30 16:23:16 +00:00
/*
* complete reading the packet .
* TODO : we should detect when blocking and abort connection if this happen
*/
if ( req - > len > ret ) {
int total , extra ;
char * base = ( char * ) & request ;
total = ret ;
while ( total < req - > len ) {
extra = req - > len - total ;
retry2 :
ret = read ( pollInfos [ nr ] . fd , base + total , extra ) ;
if ( ret < 0 ) {
if ( errno = = EINTR ) {
if ( debug > 0 )
fprintf ( stderr ,
" read socket %d from client %d interrupted \n " ,
pollInfos [ nr ] . fd , nr ) ;
goto retry2 ;
}
fprintf ( stderr , " Failed to read socket %d from client %d \n " ,
pollInfos [ nr ] . fd , nr ) ;
proxyCloseClientSocket ( nr ) ;
return ( - 1 ) ;
}
if ( ret = = 0 ) {
if ( debug )
fprintf ( stderr ,
" end of stream from client %d on socket %d \n " ,
nr , pollInfos [ nr ] . fd ) ;
proxyCloseClientSocket ( nr ) ;
return ( - 1 ) ;
}
total + = ret ;
}
}
2006-06-28 18:19:13 +00:00
switch ( req - > command ) {
case VIR_PROXY_NONE :
if ( req - > len ! = sizeof ( virProxyPacket ) )
goto comm_error ;
break ;
case VIR_PROXY_VERSION :
if ( req - > len ! = sizeof ( virProxyPacket ) )
goto comm_error ;
2006-06-29 14:44:37 +00:00
req - > data . larg = xenVersion ;
2006-06-28 18:19:13 +00:00
break ;
2006-06-29 14:44:37 +00:00
case VIR_PROXY_LIST : {
int maxids ;
if ( req - > len ! = sizeof ( virProxyPacket ) )
goto comm_error ;
2006-06-29 22:12:47 +00:00
maxids = sizeof ( request . extra . arg ) / sizeof ( int ) ;
ret = xenHypervisorListDomains ( conn , & request . extra . arg [ 0 ] ,
2006-06-29 14:44:37 +00:00
maxids ) ;
if ( ret < 0 ) {
req - > len = sizeof ( virProxyPacket ) ;
req - > data . arg = 0 ;
} else {
req - > len = sizeof ( virProxyPacket ) + ret * sizeof ( int ) ;
req - > data . arg = ret ;
}
break ;
}
2006-06-28 18:19:13 +00:00
case VIR_PROXY_NUM_DOMAIN :
2006-06-29 14:44:37 +00:00
if ( req - > len ! = sizeof ( virProxyPacket ) )
goto comm_error ;
req - > data . arg = xenHypervisorNumOfDomains ( conn ) ;
break ;
case VIR_PROXY_MAX_MEMORY :
2006-06-29 22:12:47 +00:00
if ( req - > len ! = sizeof ( virProxyPacket ) )
goto comm_error ;
req - > data . larg = xenHypervisorGetDomMaxMemory ( conn , req - > data . arg ) ;
break ;
2006-06-29 14:44:37 +00:00
case VIR_PROXY_DOMAIN_INFO :
2006-06-29 23:53:31 +00:00
if ( req - > len ! = sizeof ( virProxyPacket ) )
goto comm_error ;
memset ( & request . extra . dinfo , 0 , sizeof ( virDomainInfo ) ) ;
ret = xenHypervisorGetDomInfo ( conn , req - > data . arg ,
& request . extra . dinfo ) ;
if ( ret < 0 ) {
req - > data . arg = - 1 ;
} else {
req - > len + = sizeof ( virDomainInfo ) ;
}
break ;
case VIR_PROXY_LOOKUP_ID : {
char * name = NULL ;
Mon Jan 23 14:36:18 IST 2007 Mark McLoughlin <markmc@redhat.com>
* include/libvirt/libvirt.h.in: add VIR_UUID_BUFLEN and
VIR_UUID_STRING_BUFLEN
* libvirt/proxy/libvirt_proxy.c, libvirt/src/hash.c,
libvirt/src/internal.h, libvirt/src/libvirt.c,
libvirt/src/proxy_internal.c, libvirt/src/test.c,
libvirt/src/virsh.c, libvirt/src/xend_internal.c,
libvirt/src/xm_internal.c, libvirt/src/xml.c,
libvirt/python/libvir.c: use them
2007-01-23 14:39:45 +00:00
unsigned char uuid [ VIR_UUID_BUFLEN ] ;
2006-07-07 18:58:35 +00:00
int len ;
2006-06-29 23:53:31 +00:00
if ( req - > len ! = sizeof ( virProxyPacket ) )
goto comm_error ;
2006-07-07 18:58:35 +00:00
if ( xenDaemonDomainLookupByID ( conn , req - > data . arg , & name , uuid ) < 0 ) {
2006-06-29 23:53:31 +00:00
req - > data . arg = - 1 ;
} else {
len = strlen ( name ) ;
if ( len > 1000 ) {
len = 1000 ;
name [ 1000 ] = 0 ;
}
Mon Jan 23 14:36:18 IST 2007 Mark McLoughlin <markmc@redhat.com>
* include/libvirt/libvirt.h.in: add VIR_UUID_BUFLEN and
VIR_UUID_STRING_BUFLEN
* libvirt/proxy/libvirt_proxy.c, libvirt/src/hash.c,
libvirt/src/internal.h, libvirt/src/libvirt.c,
libvirt/src/proxy_internal.c, libvirt/src/test.c,
libvirt/src/virsh.c, libvirt/src/xend_internal.c,
libvirt/src/xm_internal.c, libvirt/src/xml.c,
libvirt/python/libvir.c: use them
2007-01-23 14:39:45 +00:00
req - > len + = VIR_UUID_BUFLEN + len + 1 ;
memcpy ( & request . extra . str [ 0 ] , uuid , VIR_UUID_BUFLEN ) ;
strcpy ( & request . extra . str [ VIR_UUID_BUFLEN ] , name ) ;
2006-06-29 23:53:31 +00:00
}
2006-07-07 18:58:35 +00:00
if ( name )
free ( name ) ;
2006-06-29 23:53:31 +00:00
break ;
}
2006-06-30 16:23:16 +00:00
case VIR_PROXY_LOOKUP_UUID : {
char * * names ;
char * * tmp ;
int ident , len ;
char * name = NULL ;
Mon Jan 23 14:36:18 IST 2007 Mark McLoughlin <markmc@redhat.com>
* include/libvirt/libvirt.h.in: add VIR_UUID_BUFLEN and
VIR_UUID_STRING_BUFLEN
* libvirt/proxy/libvirt_proxy.c, libvirt/src/hash.c,
libvirt/src/internal.h, libvirt/src/libvirt.c,
libvirt/src/proxy_internal.c, libvirt/src/test.c,
libvirt/src/virsh.c, libvirt/src/xend_internal.c,
libvirt/src/xm_internal.c, libvirt/src/xml.c,
libvirt/python/libvir.c: use them
2007-01-23 14:39:45 +00:00
unsigned char uuid [ VIR_UUID_BUFLEN ] ;
2006-06-30 16:23:16 +00:00
Mon Jan 23 14:36:18 IST 2007 Mark McLoughlin <markmc@redhat.com>
* include/libvirt/libvirt.h.in: add VIR_UUID_BUFLEN and
VIR_UUID_STRING_BUFLEN
* libvirt/proxy/libvirt_proxy.c, libvirt/src/hash.c,
libvirt/src/internal.h, libvirt/src/libvirt.c,
libvirt/src/proxy_internal.c, libvirt/src/test.c,
libvirt/src/virsh.c, libvirt/src/xend_internal.c,
libvirt/src/xm_internal.c, libvirt/src/xml.c,
libvirt/python/libvir.c: use them
2007-01-23 14:39:45 +00:00
if ( req - > len ! = sizeof ( virProxyPacket ) + VIR_UUID_BUFLEN )
2006-06-30 16:23:16 +00:00
goto comm_error ;
/*
* Xend API forces to collect the full domain list by names , and
* then query each of them until the id is found
*/
names = xenDaemonListDomainsOld ( conn ) ;
tmp = names ;
if ( names ! = NULL ) {
while ( * tmp ! = NULL ) {
ident = xenDaemonDomainLookupByName_ids ( conn , * tmp , & uuid [ 0 ] ) ;
Mon Jan 23 14:36:18 IST 2007 Mark McLoughlin <markmc@redhat.com>
* include/libvirt/libvirt.h.in: add VIR_UUID_BUFLEN and
VIR_UUID_STRING_BUFLEN
* libvirt/proxy/libvirt_proxy.c, libvirt/src/hash.c,
libvirt/src/internal.h, libvirt/src/libvirt.c,
libvirt/src/proxy_internal.c, libvirt/src/test.c,
libvirt/src/virsh.c, libvirt/src/xend_internal.c,
libvirt/src/xm_internal.c, libvirt/src/xml.c,
libvirt/python/libvir.c: use them
2007-01-23 14:39:45 +00:00
if ( ! memcmp ( uuid , & request . extra . str [ 0 ] , VIR_UUID_BUFLEN ) ) {
2006-06-30 16:23:16 +00:00
name = * tmp ;
break ;
}
tmp + + ;
}
}
if ( name = = NULL ) {
/* not found */
req - > data . arg = - 1 ;
req - > len = sizeof ( virProxyPacket ) ;
} else {
len = strlen ( name ) ;
if ( len > 1000 ) {
len = 1000 ;
name [ 1000 ] = 0 ;
}
req - > len = sizeof ( virProxyPacket ) + len + 1 ;
strcpy ( & request . extra . str [ 0 ] , name ) ;
req - > data . arg = ident ;
}
free ( names ) ;
break ;
}
case VIR_PROXY_LOOKUP_NAME : {
int ident ;
Mon Jan 23 14:36:18 IST 2007 Mark McLoughlin <markmc@redhat.com>
* include/libvirt/libvirt.h.in: add VIR_UUID_BUFLEN and
VIR_UUID_STRING_BUFLEN
* libvirt/proxy/libvirt_proxy.c, libvirt/src/hash.c,
libvirt/src/internal.h, libvirt/src/libvirt.c,
libvirt/src/proxy_internal.c, libvirt/src/test.c,
libvirt/src/virsh.c, libvirt/src/xend_internal.c,
libvirt/src/xm_internal.c, libvirt/src/xml.c,
libvirt/python/libvir.c: use them
2007-01-23 14:39:45 +00:00
unsigned char uuid [ VIR_UUID_BUFLEN ] ;
2006-06-30 16:23:16 +00:00
if ( req - > len > sizeof ( virProxyPacket ) + 1000 )
goto comm_error ;
ident = xenDaemonDomainLookupByName_ids ( conn ,
& request . extra . str [ 0 ] , & uuid [ 0 ] ) ;
if ( ident < 0 ) {
/* not found */
req - > data . arg = - 1 ;
req - > len = sizeof ( virProxyPacket ) ;
} else {
Mon Jan 23 14:36:18 IST 2007 Mark McLoughlin <markmc@redhat.com>
* include/libvirt/libvirt.h.in: add VIR_UUID_BUFLEN and
VIR_UUID_STRING_BUFLEN
* libvirt/proxy/libvirt_proxy.c, libvirt/src/hash.c,
libvirt/src/internal.h, libvirt/src/libvirt.c,
libvirt/src/proxy_internal.c, libvirt/src/test.c,
libvirt/src/virsh.c, libvirt/src/xend_internal.c,
libvirt/src/xm_internal.c, libvirt/src/xml.c,
libvirt/python/libvir.c: use them
2007-01-23 14:39:45 +00:00
req - > len = sizeof ( virProxyPacket ) + VIR_UUID_BUFLEN ;
memcpy ( & request . extra . str [ 0 ] , uuid , VIR_UUID_BUFLEN ) ;
2006-06-30 16:23:16 +00:00
req - > data . arg = ident ;
}
break ;
}
2006-06-29 14:44:37 +00:00
case VIR_PROXY_NODE_INFO :
2006-07-03 11:12:12 +00:00
if ( req - > len ! = sizeof ( virProxyPacket ) )
goto comm_error ;
/*
* Hum , could we expect those informations to be unmutable and
* cache them ? Since it ' s probably an unfrequent call better
* not make assumption and do the xend RPC each call .
*/
ret = xenDaemonNodeGetInfo ( conn , & request . extra . ninfo ) ;
if ( ret < 0 ) {
req - > data . arg = - 1 ;
req - > len = sizeof ( virProxyPacket ) ;
} else {
req - > data . arg = 0 ;
req - > len = sizeof ( virProxyPacket ) + sizeof ( virNodeInfo ) ;
}
2006-06-28 18:19:13 +00:00
break ;
2007-04-30 16:58:26 +00:00
case VIR_PROXY_GET_CAPABILITIES :
if ( req - > len ! = sizeof ( virProxyPacket ) )
goto comm_error ;
xml = xenHypervisorGetCapabilities ( conn ) ;
if ( ! xml ) {
req - > data . arg = - 1 ;
req - > len = sizeof ( virProxyPacket ) ;
} else {
int xmllen = strlen ( xml ) ;
if ( xmllen > ( int ) sizeof ( request . extra . str ) ) {
req - > data . arg = - 2 ;
req - > len = sizeof ( virProxyPacket ) ;
} else {
req - > data . arg = 0 ;
memmove ( request . extra . str , xml , xmllen ) ;
req - > len = sizeof ( virProxyPacket ) + xmllen ;
}
free ( xml ) ;
}
break ;
2006-08-09 15:21:16 +00:00
case VIR_PROXY_DOMAIN_XML :
if ( req - > len ! = sizeof ( virProxyPacket ) )
goto comm_error ;
xml = xenDaemonDomainDumpXMLByID ( conn , request . data . arg ) ;
if ( ! xml ) {
req - > data . arg = - 1 ;
req - > len = sizeof ( virProxyPacket ) ;
} else {
int xmllen = strlen ( xml ) ;
2006-09-05 06:48:44 +00:00
if ( xmllen > ( int ) sizeof ( request . extra . str ) ) {
2006-08-09 15:21:16 +00:00
req - > data . arg = - 2 ;
req - > len = sizeof ( virProxyPacket ) ;
} else {
req - > data . arg = 0 ;
memmove ( & request . extra . str [ 0 ] , xml , xmllen ) ;
req - > len = sizeof ( virProxyPacket ) + xmllen ;
}
free ( xml ) ;
}
break ;
2006-11-07 16:28:16 +00:00
case VIR_PROXY_DOMAIN_OSTYPE :
if ( req - > len ! = sizeof ( virProxyPacket ) )
goto comm_error ;
ostype = xenStoreDomainGetOSTypeID ( conn , request . data . arg ) ;
if ( ! ostype ) {
req - > data . arg = - 1 ;
req - > len = sizeof ( virProxyPacket ) ;
} else {
int ostypelen = strlen ( ostype ) ;
if ( ostypelen > ( int ) sizeof ( request . extra . str ) ) {
req - > data . arg = - 2 ;
req - > len = sizeof ( virProxyPacket ) ;
} else {
req - > data . arg = 0 ;
memmove ( & request . extra . str [ 0 ] , ostype , ostypelen ) ;
req - > len = sizeof ( virProxyPacket ) + ostypelen ;
}
free ( ostype ) ;
}
break ;
2006-06-28 18:19:13 +00:00
default :
goto comm_error ;
}
ret = proxyWriteClientSocket ( nr , req ) ;
return ( ret ) ;
comm_error :
fprintf ( stderr ,
" Communication error with client %d: malformed packet \n " , nr ) ;
proxyCloseClientSocket ( nr ) ;
return ( - 1 ) ;
}
/************************************************************************
* *
* Main loop processing *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
* proxyProcessRequests :
*
* process requests and timers
*/
static void
proxyProcessRequests ( void ) {
int exit_timeout = 30 ;
int ret , i ;
while ( ! done ) {
/*
* wait for requests , with a one second timeout
*/
ret = poll ( & pollInfos [ 0 ] , nbClients + 1 , 1000 ) ;
if ( ret = = 0 ) { /* timeout */
2006-06-29 14:44:37 +00:00
if ( ( nbClients = = 0 ) & & ( persist = = 0 ) ) {
2006-06-28 18:19:13 +00:00
exit_timeout - - ;
if ( exit_timeout = = 0 ) {
done = 1 ;
if ( debug > 0 ) {
fprintf ( stderr , " Exitting after 30s without clients \n " ) ;
}
}
} else
exit_timeout = 30 ;
if ( debug > 1 )
fprintf ( stderr , " poll timeout \n " ) ;
continue ;
} else if ( ret < 0 ) {
if ( errno = = EINTR ) {
if ( debug > 0 )
fprintf ( stderr , " poll syscall interrupted \n " ) ;
continue ;
}
fprintf ( stderr , " poll syscall failed \n " ) ;
break ;
}
/*
* there have been I / O to process
*/
exit_timeout = 30 ;
if ( pollInfos [ 0 ] . revents ! = 0 ) {
if ( pollInfos [ 0 ] . revents & POLLIN ) {
proxyAcceptClientSocket ( ) ;
} else {
fprintf ( stderr , " Got an error %d on incoming socket %d \n " ,
pollInfos [ 0 ] . revents , pollInfos [ 0 ] . fd ) ;
break ;
}
}
/*
* process the clients in reverse order since on error or disconnect
* pollInfos is compacted to remove the given client .
*/
for ( i = nbClients ; i > 0 ; i - - ) {
if ( pollInfos [ i ] . revents & POLLIN ) {
proxyReadClientSocket ( i ) ;
} else if ( pollInfos [ i ] . revents ! = 0 ) {
fprintf ( stderr , " Got an error %d on client %d socket %d \n " ,
pollInfos [ i ] . revents , i , pollInfos [ i ] . fd ) ;
proxyCloseClientSocket ( i ) ;
}
}
}
}
/**
* proxyMainLoop :
*
* main loop for the proxy , continually try to keep the unix socket
* open , serve client requests , and process timing events .
*/
static void
proxyMainLoop ( void ) {
while ( ! done ) {
if ( proxyListenUnixSocket ( PROXY_SOCKET_PATH ) < 0 )
break ;
proxyProcessRequests ( ) ;
}
proxyCloseClientSockets ( ) ;
}
/**
* usage :
*
* dump on stdout informations about the program
*/
static void
usage ( const char * progname ) {
printf ( " Usage: %s [-v] [-v] \n " , progname ) ;
printf ( " option -v increase the verbosity level for debugging \n " ) ;
printf ( " This is a proxy for xen services used by libvirt to offer \n " ) ;
printf ( " safe and fast status information on the Xen virtualization. \n " ) ;
printf ( " This need not be run manually it's started automatically. \n " ) ;
}
/**
* main :
*
* Check that we are running with root priviledges , initialize the
* connections to the daemon and or hypervisor , and then run the main loop
*/
int main ( int argc , char * * argv ) {
int i ;
2006-09-21 15:24:37 +00:00
if ( ! setlocale ( LC_ALL , " " ) ) {
perror ( " setlocale " ) ;
return - 1 ;
}
if ( ! bindtextdomain ( GETTEXT_PACKAGE , LOCALEBASEDIR ) ) {
perror ( " bindtextdomain " ) ;
return - 1 ;
}
if ( ! textdomain ( GETTEXT_PACKAGE ) ) {
perror ( " textdomain " ) ;
return - 1 ;
}
2006-06-28 18:19:13 +00:00
for ( i = 1 ; i < argc ; i + + ) {
if ( ! strcmp ( argv [ i ] , " -v " ) ) {
debug + + ;
2006-06-29 14:44:37 +00:00
} else if ( ! strcmp ( argv [ i ] , " -no-timeout " ) ) {
persist = 1 ;
2006-06-28 18:19:13 +00:00
} else {
usage ( argv [ 0 ] ) ;
exit ( 1 ) ;
}
}
2006-09-21 15:24:37 +00:00
2006-06-28 18:19:13 +00:00
if ( geteuid ( ) ! = 0 ) {
fprintf ( stderr , " %s must be run as root or suid \n " , argv [ 0 ] ) ;
/* exit(1); */
}
2006-06-29 14:44:37 +00:00
/*
* setup a connection block
*/
memset ( conn , 0 , sizeof ( conninfos ) ) ;
conn - > magic = VIR_CONNECT_MAGIC ;
/*
* very fist thing , use the socket as an exclusive lock , this then
* allow to do timed exits , avoiding constant CPU usage in case of
* failure .
*/
if ( proxyListenUnixSocket ( PROXY_SOCKET_PATH ) < 0 )
exit ( 0 ) ;
if ( proxyInitXen ( ) = = 0 )
proxyMainLoop ( ) ;
sleep ( 1 ) ;
proxyCloseUnixSocket ( ) ;
2006-06-28 18:19:13 +00:00
exit ( 0 ) ;
}
2007-03-15 17:24:56 +00:00
2007-03-15 07:43:16 +00:00
# else /* WITHOUT_XEN */
int main ( void ) {
fprintf ( stderr , " libvirt was compiled without Xen support \n " ) ;
exit ( 1 ) ;
}
# endif /* WITH_XEN */
2007-03-15 17:24:56 +00:00
/*
* vim : set tabstop = 4 :
* vim : set shiftwidth = 4 :
* vim : set expandtab :
*/
/*
* Local variables :
* indent - tabs - mode : nil
* c - indent - level : 4
* c - basic - offset : 4
* tab - width : 4
* End :
*/