2007-02-14 01:40:09 +00:00
/*
* qemud . c : daemon start of day , guest process & i / o management
*
2009-01-12 18:22:32 +00:00
* Copyright ( C ) 2006 , 2007 , 2008 , 2009 Red Hat , Inc .
2007-02-14 01:40:09 +00:00
* 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 >
*/
2008-01-29 18:15:54 +00:00
# include <config.h>
2007-02-14 15:42:55 +00:00
2007-02-14 01:40:09 +00:00
# include <sys/types.h>
# include <sys/wait.h>
# include <sys/stat.h>
# include <unistd.h>
# include <fcntl.h>
# include <limits.h>
# include <sys/socket.h>
# include <sys/un.h>
# include <sys/poll.h>
# include <netinet/in.h>
2007-06-11 12:04:54 +00:00
# include <netinet/tcp.h>
2007-02-14 01:40:09 +00:00
# include <netdb.h>
# include <stdlib.h>
# include <pwd.h>
# include <stdio.h>
2007-02-16 18:30:55 +00:00
# include <stdarg.h>
# include <syslog.h>
2007-02-14 01:40:09 +00:00
# include <string.h>
# include <errno.h>
# include <getopt.h>
2007-06-11 12:04:54 +00:00
# include <fnmatch.h>
2007-09-19 02:28:01 +00:00
# include <grp.h>
2008-01-23 14:54:41 +00:00
# include <signal.h>
2008-10-28 17:46:00 +00:00
# include <netdb.h>
2007-04-10 23:17:46 +00:00
2008-11-04 23:22:06 +00:00
# include "libvirt_internal.h"
Standardize use of header files, making internal.h primary.
* qemud/internal.h, qemud/qemud.h: Rename this file so it
doesn't conflict with src/internal.h.
* HACKING: Document how header files should be used.
* qemud/Makefile.am: Add src/ directory to includes.
* qemud/event.c, qemud/mdns.c, qemud/qemud.c, qemud/remote.c,
qemud/remote_protocol.c, qemud/remote_protocol.h,
qemud/remote_protocol.x, src/buf.c, src/libvirt.c,
src/nodeinfo.c, src/qemu_conf.c, src/qemu_driver.c,
src/stats_linux.c, src/storage_backend.c, src/storage_backend_fs.c,
src/storage_backend_iscsi.c, src/storage_backend_logical.c,
src/storage_conf.c, src/storage_driver.c, src/util.c,
src/util.h, src/virsh.c, src/virterror.c, src/xend_internal.c,
src/xml.c, tests/reconnect.c, tests/xmlrpctest.c,
tests/qparamtest.c: Standardize use of header files.
* docs/*, po/*: Rebuild docs.
2008-05-23 08:24:41 +00:00
# include "qemud.h"
# include "util.h"
# include "remote_internal.h"
# include "conf.h"
2007-06-26 19:11:00 +00:00
# include "event.h"
2008-06-06 10:52:01 +00:00
# include "memory.h"
2007-09-19 01:56:55 +00:00
# ifdef HAVE_AVAHI
# include "mdns.h"
# endif
2007-02-14 01:40:09 +00:00
2008-11-21 12:16:08 +00:00
# ifdef WITH_DRIVER_MODULES
# include "driver.h"
# else
2008-11-17 12:18:18 +00:00
# ifdef WITH_QEMU
# include "qemu_driver.h"
# endif
# ifdef WITH_LXC
# include "lxc_driver.h"
# endif
2008-11-19 16:58:23 +00:00
# ifdef WITH_UML
# include "uml_driver.h"
# endif
2008-11-17 12:18:18 +00:00
# ifdef WITH_NETWORK
# include "network_driver.h"
# endif
# ifdef WITH_STORAGE_DIR
# include "storage_driver.h"
# endif
2008-11-21 12:27:11 +00:00
# ifdef WITH_NODE_DEVICES
# include "node_device.h"
# endif
2008-11-21 12:16:08 +00:00
# endif
2008-11-17 12:18:18 +00:00
2007-06-11 12:04:54 +00:00
static int godaemon = 0 ; /* -d: Be a daemon */
static int verbose = 0 ; /* -v: Verbose mode */
2007-06-26 23:48:46 +00:00
static int timeout = - 1 ; /* -t: Shutdown timeout */
2007-06-11 12:04:54 +00:00
static int sigwrite = - 1 ; /* Signal handler pipe */
2007-06-26 23:48:46 +00:00
static int ipsock = 0 ; /* -l Listen for TCP/IP */
2007-06-11 12:04:54 +00:00
2008-12-22 12:53:26 +00:00
/* Defaults for logging */
static int log_level = 3 ;
static char * log_filters = NULL ;
static char * log_outputs = NULL ;
2007-06-26 23:48:46 +00:00
/* Defaults for configuration file elements */
2007-06-11 12:04:54 +00:00
static int listen_tls = 1 ;
static int listen_tcp = 0 ;
2008-05-14 20:57:20 +00:00
static char * listen_addr = ( char * ) LIBVIRTD_LISTEN_ADDR ;
Detect heap allocation failure; factor out some duplication.
* qemud/qemud.c (tls_port, tcp_port, mdns_name, tls_allowed_ip_list):
(tls_allowed_dn_list): Remove "const", now that we free these.
(unix_sock_rw_mask): Rename from unix_sock_rw_perms, so that
the latter name can be used as a local string variable, so that the
variable name matches the config attribute name.
(unix_sock_ro_mask): Rename from unix_sock_ro_perms, likewise.
(remoteCheckDN, remoteCheckAccess): Adapt to const removal.
(qemudDispatchServer): Check for heap allocation failure.
(remoteConfigGetStringList): New function, based on code from Dan Berrangé.
(CHECK_TYPE): Remove macro.
(checkType): New function.
(GET_CONF_INT, GET_CONF_STR): New macros.
(remoteReadConfigFile): Use new macros to avoid duplication and to
check for allocation failure.
* src/conf.h (virConfTypeName): New static inline function.
2007-11-30 15:43:42 +00:00
static char * tls_port = ( char * ) LIBVIRTD_TLS_PORT ;
static char * tcp_port = ( char * ) LIBVIRTD_TCP_PORT ;
2007-06-11 12:04:54 +00:00
2007-09-19 02:28:01 +00:00
static gid_t unix_sock_gid = 0 ; /* Only root by default */
Detect heap allocation failure; factor out some duplication.
* qemud/qemud.c (tls_port, tcp_port, mdns_name, tls_allowed_ip_list):
(tls_allowed_dn_list): Remove "const", now that we free these.
(unix_sock_rw_mask): Rename from unix_sock_rw_perms, so that
the latter name can be used as a local string variable, so that the
variable name matches the config attribute name.
(unix_sock_ro_mask): Rename from unix_sock_ro_perms, likewise.
(remoteCheckDN, remoteCheckAccess): Adapt to const removal.
(qemudDispatchServer): Check for heap allocation failure.
(remoteConfigGetStringList): New function, based on code from Dan Berrangé.
(CHECK_TYPE): Remove macro.
(checkType): New function.
(GET_CONF_INT, GET_CONF_STR): New macros.
(remoteReadConfigFile): Use new macros to avoid duplication and to
check for allocation failure.
* src/conf.h (virConfTypeName): New static inline function.
2007-11-30 15:43:42 +00:00
static int unix_sock_rw_mask = 0700 ; /* Allow user only */
static int unix_sock_ro_mask = 0777 ; /* Allow world */
2007-09-19 02:28:01 +00:00
2007-12-05 18:21:27 +00:00
# if HAVE_POLKIT
static int auth_unix_rw = REMOTE_AUTH_POLKIT ;
static int auth_unix_ro = REMOTE_AUTH_POLKIT ;
# else
2007-12-05 15:34:05 +00:00
static int auth_unix_rw = REMOTE_AUTH_NONE ;
static int auth_unix_ro = REMOTE_AUTH_NONE ;
2007-12-05 18:21:27 +00:00
# endif /* HAVE_POLKIT */
2007-12-05 15:34:05 +00:00
# if HAVE_SASL
static int auth_tcp = REMOTE_AUTH_SASL ;
# else
static int auth_tcp = REMOTE_AUTH_NONE ;
# endif
static int auth_tls = REMOTE_AUTH_NONE ;
2007-09-19 01:56:55 +00:00
static int mdns_adv = 1 ;
Detect heap allocation failure; factor out some duplication.
* qemud/qemud.c (tls_port, tcp_port, mdns_name, tls_allowed_ip_list):
(tls_allowed_dn_list): Remove "const", now that we free these.
(unix_sock_rw_mask): Rename from unix_sock_rw_perms, so that
the latter name can be used as a local string variable, so that the
variable name matches the config attribute name.
(unix_sock_ro_mask): Rename from unix_sock_ro_perms, likewise.
(remoteCheckDN, remoteCheckAccess): Adapt to const removal.
(qemudDispatchServer): Check for heap allocation failure.
(remoteConfigGetStringList): New function, based on code from Dan Berrangé.
(CHECK_TYPE): Remove macro.
(checkType): New function.
(GET_CONF_INT, GET_CONF_STR): New macros.
(remoteReadConfigFile): Use new macros to avoid duplication and to
check for allocation failure.
* src/conf.h (virConfTypeName): New static inline function.
2007-11-30 15:43:42 +00:00
static char * mdns_name = NULL ;
2007-09-19 01:56:55 +00:00
2007-06-11 12:04:54 +00:00
static int tls_no_verify_certificate = 0 ;
Detect heap allocation failure; factor out some duplication.
* qemud/qemud.c (tls_port, tcp_port, mdns_name, tls_allowed_ip_list):
(tls_allowed_dn_list): Remove "const", now that we free these.
(unix_sock_rw_mask): Rename from unix_sock_rw_perms, so that
the latter name can be used as a local string variable, so that the
variable name matches the config attribute name.
(unix_sock_ro_mask): Rename from unix_sock_ro_perms, likewise.
(remoteCheckDN, remoteCheckAccess): Adapt to const removal.
(qemudDispatchServer): Check for heap allocation failure.
(remoteConfigGetStringList): New function, based on code from Dan Berrangé.
(CHECK_TYPE): Remove macro.
(checkType): New function.
(GET_CONF_INT, GET_CONF_STR): New macros.
(remoteReadConfigFile): Use new macros to avoid duplication and to
check for allocation failure.
* src/conf.h (virConfTypeName): New static inline function.
2007-11-30 15:43:42 +00:00
static char * * tls_allowed_dn_list = NULL ;
2007-06-11 12:04:54 +00:00
Detect heap allocation failure; factor out some duplication.
* qemud/qemud.c (tls_port, tcp_port, mdns_name, tls_allowed_ip_list):
(tls_allowed_dn_list): Remove "const", now that we free these.
(unix_sock_rw_mask): Rename from unix_sock_rw_perms, so that
the latter name can be used as a local string variable, so that the
variable name matches the config attribute name.
(unix_sock_ro_mask): Rename from unix_sock_ro_perms, likewise.
(remoteCheckDN, remoteCheckAccess): Adapt to const removal.
(qemudDispatchServer): Check for heap allocation failure.
(remoteConfigGetStringList): New function, based on code from Dan Berrangé.
(CHECK_TYPE): Remove macro.
(checkType): New function.
(GET_CONF_INT, GET_CONF_STR): New macros.
(remoteReadConfigFile): Use new macros to avoid duplication and to
check for allocation failure.
* src/conf.h (virConfTypeName): New static inline function.
2007-11-30 15:43:42 +00:00
static char * key_file = ( char * ) LIBVIRT_SERVERKEY ;
static char * cert_file = ( char * ) LIBVIRT_SERVERCERT ;
static char * ca_file = ( char * ) LIBVIRT_CACERT ;
static char * crl_file = ( char * ) " " ;
2007-06-11 12:04:54 +00:00
static gnutls_certificate_credentials_t x509_cred ;
static gnutls_dh_params_t dh_params ;
2008-12-04 22:18:44 +00:00
static int min_workers = 5 ;
static int max_workers = 20 ;
static int max_clients = 20 ;
2007-06-11 12:04:54 +00:00
# define DH_BITS 1024
2007-02-16 18:28:17 +00:00
2007-03-27 10:28:45 +00:00
static sig_atomic_t sig_errors = 0 ;
static int sig_lasterrno = 0 ;
2008-05-13 06:30:58 +00:00
static void sig_handler ( int sig , siginfo_t * siginfo ,
void * context ATTRIBUTE_UNUSED ) {
2007-02-16 18:28:17 +00:00
int origerrno ;
2007-03-27 10:28:45 +00:00
int r ;
2007-02-16 18:28:17 +00:00
2008-05-13 06:30:58 +00:00
/* set the sig num in the struct */
siginfo - > si_signo = sig ;
2007-02-16 18:28:17 +00:00
origerrno = errno ;
2008-05-13 06:30:58 +00:00
r = safewrite ( sigwrite , siginfo , sizeof ( * siginfo ) ) ;
2007-03-27 10:28:45 +00:00
if ( r = = - 1 ) {
sig_errors + + ;
sig_lasterrno = errno ;
}
2007-02-16 18:28:17 +00:00
errno = origerrno ;
2007-02-14 01:40:09 +00:00
}
2007-02-16 18:28:17 +00:00
2008-11-19 16:19:36 +00:00
static void qemudDispatchClientEvent ( int watch , int fd , int events , void * opaque ) ;
static void qemudDispatchServerEvent ( int watch , int fd , int events , void * opaque ) ;
2007-06-26 19:11:00 +00:00
static int qemudRegisterClientEvent ( struct qemud_server * server ,
struct qemud_client * client ,
2007-08-07 13:02:35 +00:00
int removeFirst ) ;
2007-06-26 19:11:00 +00:00
2007-07-12 14:54:45 +00:00
static int
remoteCheckCertFile ( const char * type , const char * file )
{
struct stat sb ;
if ( stat ( file , & sb ) < 0 ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " Cannot access %s '%s': %s (%d) " ) ,
2007-07-12 14:54:45 +00:00
type , file , strerror ( errno ) , errno ) ;
return - 1 ;
}
return 0 ;
}
2007-06-11 12:04:54 +00:00
static int
remoteInitializeGnuTLS ( void )
{
int err ;
/* Initialise GnuTLS. */
gnutls_global_init ( ) ;
err = gnutls_certificate_allocate_credentials ( & x509_cred ) ;
if ( err ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " gnutls_certificate_allocate_credentials: %s " ) ,
2007-06-11 12:04:54 +00:00
gnutls_strerror ( err ) ) ;
return - 1 ;
}
if ( ca_file & & ca_file [ 0 ] ! = ' \0 ' ) {
2007-07-12 14:54:45 +00:00
if ( remoteCheckCertFile ( " CA certificate " , ca_file ) < 0 )
return - 1 ;
2007-06-11 12:04:54 +00:00
qemudDebug ( " loading CA cert from %s " , ca_file ) ;
err = gnutls_certificate_set_x509_trust_file ( x509_cred , ca_file ,
GNUTLS_X509_FMT_PEM ) ;
if ( err < 0 ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " gnutls_certificate_set_x509_trust_file: %s " ) ,
2007-06-11 12:04:54 +00:00
gnutls_strerror ( err ) ) ;
return - 1 ;
}
}
if ( crl_file & & crl_file [ 0 ] ! = ' \0 ' ) {
2007-11-21 23:16:11 +00:00
if ( remoteCheckCertFile ( " CA revocation list " , crl_file ) < 0 )
2007-07-12 14:54:45 +00:00
return - 1 ;
2008-12-22 12:53:26 +00:00
DEBUG ( " loading CRL from %s " , crl_file ) ;
2007-06-11 12:04:54 +00:00
err = gnutls_certificate_set_x509_crl_file ( x509_cred , crl_file ,
GNUTLS_X509_FMT_PEM ) ;
if ( err < 0 ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " gnutls_certificate_set_x509_crl_file: %s " ) ,
2007-06-11 12:04:54 +00:00
gnutls_strerror ( err ) ) ;
return - 1 ;
}
}
if ( cert_file & & cert_file [ 0 ] ! = ' \0 ' & & key_file & & key_file [ 0 ] ! = ' \0 ' ) {
2007-07-12 14:54:45 +00:00
if ( remoteCheckCertFile ( " server certificate " , cert_file ) < 0 )
return - 1 ;
if ( remoteCheckCertFile ( " server key " , key_file ) < 0 )
return - 1 ;
2008-12-22 12:53:26 +00:00
DEBUG ( " loading cert and key from %s and %s " , cert_file , key_file ) ;
2007-06-11 12:04:54 +00:00
err =
gnutls_certificate_set_x509_key_file ( x509_cred ,
cert_file , key_file ,
GNUTLS_X509_FMT_PEM ) ;
if ( err < 0 ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " gnutls_certificate_set_x509_key_file: %s " ) ,
2007-06-11 12:04:54 +00:00
gnutls_strerror ( err ) ) ;
return - 1 ;
}
}
/* Generate Diffie Hellman parameters - for use with DHE
* kx algorithms . These should be discarded and regenerated
* once a day , once a week or once a month . Depending on the
* security requirements .
*/
err = gnutls_dh_params_init ( & dh_params ) ;
if ( err < 0 ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " gnutls_dh_params_init: %s " ) , gnutls_strerror ( err ) ) ;
2007-06-11 12:04:54 +00:00
return - 1 ;
}
err = gnutls_dh_params_generate2 ( dh_params , DH_BITS ) ;
if ( err < 0 ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " gnutls_dh_params_generate2: %s " ) , gnutls_strerror ( err ) ) ;
2007-06-11 12:04:54 +00:00
return - 1 ;
}
gnutls_certificate_set_dh_params ( x509_cred , dh_params ) ;
return 0 ;
}
2008-10-23 13:18:18 +00:00
static void
2008-11-19 16:19:36 +00:00
qemudDispatchSignalEvent ( int watch ATTRIBUTE_UNUSED ,
int fd ATTRIBUTE_UNUSED ,
2008-10-23 13:18:18 +00:00
int events ATTRIBUTE_UNUSED ,
void * opaque ) {
2007-06-26 19:11:00 +00:00
struct qemud_server * server = ( struct qemud_server * ) opaque ;
2008-05-13 06:30:58 +00:00
siginfo_t siginfo ;
2007-02-16 18:28:17 +00:00
int ret ;
2008-12-04 22:16:40 +00:00
pthread_mutex_lock ( & server - > lock ) ;
2008-05-13 06:30:58 +00:00
if ( saferead ( server - > sigread , & siginfo , sizeof ( siginfo ) ) ! = sizeof ( siginfo ) ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " Failed to read from signal pipe: %s " ) , strerror ( errno ) ) ;
2008-12-04 22:16:40 +00:00
pthread_mutex_unlock ( & server - > lock ) ;
2007-06-26 19:11:00 +00:00
return ;
2007-02-16 18:30:55 +00:00
}
2007-02-16 18:28:17 +00:00
ret = 0 ;
2008-05-13 06:30:58 +00:00
switch ( siginfo . si_signo ) {
2007-02-16 18:28:17 +00:00
case SIGHUP :
2009-01-06 18:32:03 +00:00
VIR_INFO0 ( _ ( " Reloading configuration on SIGHUP " ) ) ;
2007-06-26 22:56:14 +00:00
if ( virStateReload ( ) < 0 )
2009-01-06 18:32:03 +00:00
VIR_WARN0 ( _ ( " Error while reloading drivers " ) ) ;
2007-02-16 18:28:17 +00:00
break ;
case SIGINT :
2007-02-19 16:59:15 +00:00
case SIGQUIT :
2007-02-16 18:28:17 +00:00
case SIGTERM :
2009-01-06 18:32:03 +00:00
VIR_WARN ( _ ( " Shutting down on signal %d " ) , siginfo . si_signo ) ;
2007-02-16 18:28:17 +00:00
server - > shutdown = 1 ;
break ;
default :
2009-01-06 18:32:03 +00:00
VIR_INFO ( _ ( " Received unexpected signal %d " ) , siginfo . si_signo ) ;
2007-02-16 18:28:17 +00:00
break ;
}
2007-06-26 19:11:00 +00:00
if ( ret ! = 0 )
server - > shutdown = 1 ;
2008-12-04 22:16:40 +00:00
pthread_mutex_unlock ( & server - > lock ) ;
2007-02-16 18:28:17 +00:00
}
2008-12-04 22:14:15 +00:00
int qemudSetCloseExec ( int fd ) {
2007-02-14 01:40:09 +00:00
int flags ;
2007-02-16 18:30:55 +00:00
if ( ( flags = fcntl ( fd , F_GETFD ) ) < 0 )
goto error ;
2007-02-14 01:40:09 +00:00
flags | = FD_CLOEXEC ;
2007-02-16 18:30:55 +00:00
if ( ( fcntl ( fd , F_SETFD , flags ) ) < 0 )
goto error ;
2007-02-14 01:40:09 +00:00
return 0 ;
2007-02-16 18:30:55 +00:00
error :
2009-01-06 18:32:03 +00:00
VIR_ERROR0 ( _ ( " Failed to set close-on-exec file descriptor flag " ) ) ;
2007-02-16 18:30:55 +00:00
return - 1 ;
2007-02-14 01:40:09 +00:00
}
2008-12-04 22:14:15 +00:00
int qemudSetNonBlock ( int fd ) {
2007-02-14 01:40:09 +00:00
int flags ;
2007-02-16 18:30:55 +00:00
if ( ( flags = fcntl ( fd , F_GETFL ) ) < 0 )
goto error ;
2007-02-14 01:40:09 +00:00
flags | = O_NONBLOCK ;
2007-02-16 18:30:55 +00:00
if ( ( fcntl ( fd , F_SETFL , flags ) ) < 0 )
goto error ;
2007-02-14 01:40:09 +00:00
return 0 ;
2007-02-16 18:30:55 +00:00
error :
2009-01-06 18:32:03 +00:00
VIR_ERROR0 ( _ ( " Failed to set non-blocking file descriptor flag " ) ) ;
2007-02-16 18:30:55 +00:00
return - 1 ;
}
2007-02-14 01:40:09 +00:00
static int qemudGoDaemon ( void ) {
int pid = fork ( ) ;
switch ( pid ) {
case 0 :
{
int stdinfd = - 1 ;
int stdoutfd = - 1 ;
2007-02-16 18:26:18 +00:00
int nextpid ;
2007-02-14 01:40:09 +00:00
2008-12-17 18:04:55 +00:00
if ( ( stdinfd = open ( " /dev/null " , O_RDONLY ) ) < 0 )
2007-02-14 01:40:09 +00:00
goto cleanup ;
2008-12-17 18:04:55 +00:00
if ( ( stdoutfd = open ( " /dev/null " , O_WRONLY ) ) < 0 )
2007-02-14 01:40:09 +00:00
goto cleanup ;
if ( dup2 ( stdinfd , STDIN_FILENO ) ! = STDIN_FILENO )
goto cleanup ;
if ( dup2 ( stdoutfd , STDOUT_FILENO ) ! = STDOUT_FILENO )
goto cleanup ;
if ( dup2 ( stdoutfd , STDERR_FILENO ) ! = STDERR_FILENO )
goto cleanup ;
if ( close ( stdinfd ) < 0 )
goto cleanup ;
stdinfd = - 1 ;
if ( close ( stdoutfd ) < 0 )
goto cleanup ;
stdoutfd = - 1 ;
if ( setsid ( ) < 0 )
goto cleanup ;
nextpid = fork ( ) ;
switch ( nextpid ) {
case 0 :
return 0 ;
case - 1 :
return - 1 ;
default :
2008-03-11 14:22:12 +00:00
_exit ( 0 ) ;
2007-02-14 01:40:09 +00:00
}
cleanup :
if ( stdoutfd ! = - 1 )
close ( stdoutfd ) ;
if ( stdinfd ! = - 1 )
close ( stdinfd ) ;
return - 1 ;
}
case - 1 :
return - 1 ;
default :
{
int got , status = 0 ;
/* We wait to make sure the next child forked
successfully */
if ( ( got = waitpid ( pid , & status , 0 ) ) < 0 | |
got ! = pid | |
status ! = 0 ) {
return - 1 ;
}
2008-03-11 14:22:12 +00:00
_exit ( 0 ) ;
2007-02-14 01:40:09 +00:00
}
}
}
2007-02-23 12:48:36 +00:00
static int qemudWritePidFile ( const char * pidFile ) {
int fd ;
FILE * fh ;
if ( pidFile [ 0 ] = = ' \0 ' )
return 0 ;
if ( ( fd = open ( pidFile , O_WRONLY | O_CREAT | O_EXCL , 0644 ) ) < 0 ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " Failed to open pid file '%s' : %s " ) ,
pidFile , strerror ( errno ) ) ;
2007-02-23 12:48:36 +00:00
return - 1 ;
}
if ( ! ( fh = fdopen ( fd , " w " ) ) ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " Failed to fdopen pid file '%s' : %s " ) ,
pidFile , strerror ( errno ) ) ;
2007-02-23 12:48:36 +00:00
close ( fd ) ;
return - 1 ;
}
if ( fprintf ( fh , " %lu \n " , ( unsigned long ) getpid ( ) ) < 0 ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " Failed to write to pid file '%s' : %s " ) ,
pidFile , strerror ( errno ) ) ;
2007-02-23 12:48:36 +00:00
close ( fd ) ;
return - 1 ;
}
if ( fclose ( fh ) = = EOF ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " Failed to close pid file '%s' : %s " ) ,
pidFile , strerror ( errno ) ) ;
2007-02-23 12:48:36 +00:00
return - 1 ;
}
return 0 ;
}
2007-02-14 01:40:09 +00:00
static int qemudListenUnix ( struct qemud_server * server ,
2007-12-05 15:34:05 +00:00
const char * path , int readonly , int auth ) {
2008-06-06 10:52:01 +00:00
struct qemud_socket * sock ;
2007-02-14 01:40:09 +00:00
struct sockaddr_un addr ;
mode_t oldmask ;
2007-09-19 02:28:01 +00:00
gid_t oldgrp ;
2007-02-14 01:40:09 +00:00
2008-06-06 10:52:01 +00:00
if ( VIR_ALLOC ( sock ) < 0 ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR ( " %s " , _ ( " Failed to allocate memory for struct qemud_socket " ) ) ;
2007-02-14 01:40:09 +00:00
return - 1 ;
2007-02-16 18:30:55 +00:00
}
2007-02-14 01:40:09 +00:00
sock - > readonly = readonly ;
2007-09-19 01:56:55 +00:00
sock - > port = - 1 ;
2007-12-05 15:27:08 +00:00
sock - > type = QEMUD_SOCK_TYPE_UNIX ;
2007-12-05 15:34:05 +00:00
sock - > auth = auth ;
2007-02-14 01:40:09 +00:00
2007-02-16 18:30:55 +00:00
if ( ( sock - > fd = socket ( PF_UNIX , SOCK_STREAM , 0 ) ) < 0 ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " Failed to create socket: %s " ) ,
strerror ( errno ) ) ;
2007-06-26 19:11:00 +00:00
goto cleanup ;
2007-02-16 18:30:55 +00:00
}
2007-02-14 01:40:09 +00:00
2007-02-16 18:30:55 +00:00
if ( qemudSetCloseExec ( sock - > fd ) < 0 | |
qemudSetNonBlock ( sock - > fd ) < 0 )
2007-06-26 19:11:00 +00:00
goto cleanup ;
2007-02-14 01:40:09 +00:00
memset ( & addr , 0 , sizeof ( addr ) ) ;
addr . sun_family = AF_UNIX ;
strncpy ( addr . sun_path , path , sizeof ( addr . sun_path ) - 1 ) ;
if ( addr . sun_path [ 0 ] = = ' @ ' )
addr . sun_path [ 0 ] = ' \0 ' ;
2007-09-19 02:28:01 +00:00
oldgrp = getgid ( ) ;
Detect heap allocation failure; factor out some duplication.
* qemud/qemud.c (tls_port, tcp_port, mdns_name, tls_allowed_ip_list):
(tls_allowed_dn_list): Remove "const", now that we free these.
(unix_sock_rw_mask): Rename from unix_sock_rw_perms, so that
the latter name can be used as a local string variable, so that the
variable name matches the config attribute name.
(unix_sock_ro_mask): Rename from unix_sock_ro_perms, likewise.
(remoteCheckDN, remoteCheckAccess): Adapt to const removal.
(qemudDispatchServer): Check for heap allocation failure.
(remoteConfigGetStringList): New function, based on code from Dan Berrangé.
(CHECK_TYPE): Remove macro.
(checkType): New function.
(GET_CONF_INT, GET_CONF_STR): New macros.
(remoteReadConfigFile): Use new macros to avoid duplication and to
check for allocation failure.
* src/conf.h (virConfTypeName): New static inline function.
2007-11-30 15:43:42 +00:00
oldmask = umask ( readonly ? ~ unix_sock_ro_mask : ~ unix_sock_rw_mask ) ;
2007-09-19 02:28:01 +00:00
if ( getuid ( ) = = 0 )
setgid ( unix_sock_gid ) ;
2007-02-16 18:30:55 +00:00
if ( bind ( sock - > fd , ( struct sockaddr * ) & addr , sizeof ( addr ) ) < 0 ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " Failed to bind socket to '%s': %s " ) ,
path , strerror ( errno ) ) ;
2007-06-26 19:11:00 +00:00
goto cleanup ;
2007-02-16 18:30:55 +00:00
}
2007-02-14 01:40:09 +00:00
umask ( oldmask ) ;
2007-09-19 02:28:01 +00:00
if ( getuid ( ) = = 0 )
setgid ( oldgrp ) ;
2007-02-14 01:40:09 +00:00
2007-02-16 18:30:55 +00:00
if ( listen ( sock - > fd , 30 ) < 0 ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " Failed to listen for connections on '%s': %s " ) ,
path , strerror ( errno ) ) ;
2007-06-26 19:11:00 +00:00
goto cleanup ;
}
2008-11-19 16:19:36 +00:00
if ( ( sock - > watch = virEventAddHandleImpl ( sock - > fd ,
VIR_EVENT_HANDLE_READABLE |
VIR_EVENT_HANDLE_ERROR |
VIR_EVENT_HANDLE_HANGUP ,
qemudDispatchServerEvent ,
2008-11-19 16:24:01 +00:00
server , NULL ) ) < 0 ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR0 ( _ ( " Failed to add server event callback " ) ) ;
2007-06-26 19:11:00 +00:00
goto cleanup ;
2007-02-16 18:30:55 +00:00
}
2007-02-14 01:40:09 +00:00
2007-06-26 19:11:00 +00:00
sock - > next = server - > sockets ;
server - > sockets = sock ;
server - > nsockets + + ;
2007-02-14 01:40:09 +00:00
return 0 ;
2007-06-26 19:11:00 +00:00
cleanup :
if ( sock - > fd )
close ( sock - > fd ) ;
free ( sock ) ;
return - 1 ;
2007-02-14 01:40:09 +00:00
}
2007-06-11 12:04:54 +00:00
// See: http://people.redhat.com/drepper/userapi-ipv6.html
static int
2008-05-14 20:57:20 +00:00
remoteMakeSockets ( int * fds , int max_fds , int * nfds_r , const char * node , const char * service )
2007-06-11 12:04:54 +00:00
{
struct addrinfo * ai ;
struct addrinfo hints ;
memset ( & hints , 0 , sizeof hints ) ;
hints . ai_flags = AI_PASSIVE | AI_ADDRCONFIG ;
hints . ai_socktype = SOCK_STREAM ;
2008-05-14 20:57:20 +00:00
int e = getaddrinfo ( node , service , & hints , & ai ) ;
2007-06-11 12:04:54 +00:00
if ( e ! = 0 ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " getaddrinfo: %s \n " ) , gai_strerror ( e ) ) ;
2007-06-11 12:04:54 +00:00
return - 1 ;
}
struct addrinfo * runp = ai ;
while ( runp & & * nfds_r < max_fds ) {
fds [ * nfds_r ] = socket ( runp - > ai_family , runp - > ai_socktype ,
runp - > ai_protocol ) ;
if ( fds [ * nfds_r ] = = - 1 ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " socket: %s " ) , strerror ( errno ) ) ;
2007-06-11 12:04:54 +00:00
return - 1 ;
}
int opt = 1 ;
setsockopt ( fds [ * nfds_r ] , SOL_SOCKET , SO_REUSEADDR , & opt , sizeof opt ) ;
if ( bind ( fds [ * nfds_r ] , runp - > ai_addr , runp - > ai_addrlen ) = = - 1 ) {
if ( errno ! = EADDRINUSE ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " bind: %s " ) , strerror ( errno ) ) ;
2007-06-11 12:04:54 +00:00
return - 1 ;
}
close ( fds [ * nfds_r ] ) ;
}
else {
if ( listen ( fds [ * nfds_r ] , SOMAXCONN ) = = - 1 ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " listen: %s " ) , strerror ( errno ) ) ;
2007-06-11 12:04:54 +00:00
return - 1 ;
}
+ + * nfds_r ;
}
runp = runp - > ai_next ;
}
2007-02-23 09:10:28 +00:00
2007-06-11 12:04:54 +00:00
freeaddrinfo ( ai ) ;
return 0 ;
}
/* Listen on the named/numbered TCP port. On a machine with IPv4 and
* IPv6 interfaces this may generate several sockets .
*/
static int
remoteListenTCP ( struct qemud_server * server ,
2008-05-14 21:23:02 +00:00
const char * addr ,
2007-06-11 12:04:54 +00:00
const char * port ,
2007-12-05 15:27:08 +00:00
int type ,
2007-12-05 15:24:15 +00:00
int auth )
2007-06-11 12:04:54 +00:00
{
int fds [ 2 ] ;
int nfds = 0 ;
2007-02-23 09:10:28 +00:00
int i ;
2007-06-11 12:04:54 +00:00
struct qemud_socket * sock ;
2008-05-14 20:57:20 +00:00
if ( remoteMakeSockets ( fds , 2 , & nfds , addr , port ) = = - 1 )
2007-06-11 12:04:54 +00:00
return - 1 ;
for ( i = 0 ; i < nfds ; + + i ) {
2007-09-19 01:56:55 +00:00
struct sockaddr_storage sa ;
socklen_t salen = sizeof ( sa ) ;
2008-06-06 10:52:01 +00:00
if ( VIR_ALLOC ( sock ) < 0 ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " remoteListenTCP: calloc: %s " ) , strerror ( errno ) ) ;
2008-06-06 10:52:01 +00:00
goto cleanup ;
2007-06-11 12:04:54 +00:00
}
sock - > readonly = 0 ;
sock - > next = server - > sockets ;
server - > sockets = sock ;
server - > nsockets + + ;
sock - > fd = fds [ i ] ;
2007-12-05 15:27:08 +00:00
sock - > type = type ;
2007-12-05 15:24:15 +00:00
sock - > auth = auth ;
2007-02-14 01:40:09 +00:00
2007-09-19 01:56:55 +00:00
if ( getsockname ( sock - > fd , ( struct sockaddr * ) ( & sa ) , & salen ) < 0 )
2008-06-06 10:52:01 +00:00
goto cleanup ;
2007-09-19 01:56:55 +00:00
if ( sa . ss_family = = AF_INET )
sock - > port = htons ( ( ( struct sockaddr_in * ) & sa ) - > sin_port ) ;
2007-11-26 11:56:41 +00:00
# ifdef AF_INET6
2007-09-19 01:56:55 +00:00
else if ( sa . ss_family = = AF_INET6 )
sock - > port = htons ( ( ( struct sockaddr_in6 * ) & sa ) - > sin6_port ) ;
2007-11-26 11:56:41 +00:00
# endif
2007-09-19 01:56:55 +00:00
else
sock - > port = - 1 ;
2007-06-11 12:04:54 +00:00
if ( qemudSetCloseExec ( sock - > fd ) < 0 | |
qemudSetNonBlock ( sock - > fd ) < 0 )
2008-06-06 10:52:01 +00:00
goto cleanup ;
2007-06-11 12:04:54 +00:00
if ( listen ( sock - > fd , 30 ) < 0 ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " remoteListenTCP: listen: %s " ) , strerror ( errno ) ) ;
2008-06-06 10:52:01 +00:00
goto cleanup ;
2007-02-20 09:04:27 +00:00
}
2007-06-26 19:11:00 +00:00
2008-11-19 16:19:36 +00:00
if ( ( sock - > watch = virEventAddHandleImpl ( sock - > fd ,
VIR_EVENT_HANDLE_READABLE |
VIR_EVENT_HANDLE_ERROR |
VIR_EVENT_HANDLE_HANGUP ,
qemudDispatchServerEvent ,
2008-11-19 16:24:01 +00:00
server , NULL ) ) < 0 ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR0 ( _ ( " Failed to add server event callback " ) ) ;
2008-06-06 10:52:01 +00:00
goto cleanup ;
2007-06-26 19:11:00 +00:00
}
2007-06-11 12:04:54 +00:00
}
return 0 ;
2008-06-06 10:52:01 +00:00
cleanup :
for ( i = 0 ; i < nfds ; + + i )
close ( fds [ 0 ] ) ;
return - 1 ;
2007-06-11 12:04:54 +00:00
}
static int qemudInitPaths ( struct qemud_server * server ,
char * sockname ,
char * roSockname ,
int maxlen ) {
2007-06-26 23:48:46 +00:00
uid_t uid = geteuid ( ) ;
2007-06-11 12:04:54 +00:00
2007-06-26 23:48:46 +00:00
if ( ! uid ) {
2007-06-11 12:04:54 +00:00
if ( snprintf ( sockname , maxlen , " %s/run/libvirt/libvirt-sock " ,
LOCAL_STATE_DIR ) > = maxlen )
2007-02-16 18:30:55 +00:00
goto snprintf_error ;
2007-02-14 01:40:09 +00:00
unlink ( sockname ) ;
2007-06-11 12:04:54 +00:00
if ( snprintf ( roSockname , maxlen , " %s/run/libvirt/libvirt-sock-ro " ,
LOCAL_STATE_DIR ) > = maxlen )
2007-02-16 18:30:55 +00:00
goto snprintf_error ;
2007-02-14 01:40:09 +00:00
2007-03-06 16:51:48 +00:00
unlink ( roSockname ) ;
2007-05-18 18:36:24 +00:00
2007-06-26 23:48:46 +00:00
if ( snprintf ( server - > logDir , PATH_MAX , " %s/log/libvirt/ " , LOCAL_STATE_DIR ) > = PATH_MAX )
2007-05-18 18:36:24 +00:00
goto snprintf_error ;
2007-02-14 01:40:09 +00:00
} else {
2007-06-11 12:04:54 +00:00
struct passwd * pw ;
2007-06-26 23:48:46 +00:00
if ( ! ( pw = getpwuid ( uid ) ) ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " Failed to find user record for uid '%d': %s " ) ,
2007-06-26 23:48:46 +00:00
uid , strerror ( errno ) ) ;
return - 1 ;
}
2007-06-11 12:04:54 +00:00
2007-06-26 23:48:46 +00:00
if ( snprintf ( sockname , maxlen , " @%s/.libvirt/libvirt-sock " , pw - > pw_dir ) > = maxlen )
goto snprintf_error ;
2007-06-11 12:04:54 +00:00
2007-06-26 23:48:46 +00:00
if ( snprintf ( server - > logDir , PATH_MAX , " %s/.libvirt/log " , pw - > pw_dir ) > = PATH_MAX )
goto snprintf_error ;
2007-06-26 22:13:21 +00:00
2007-06-11 12:04:54 +00:00
} /* !remote */
2007-02-14 01:40:09 +00:00
return 0 ;
2007-02-16 18:30:55 +00:00
snprintf_error :
2009-01-06 18:32:03 +00:00
VIR_ERROR ( " %s " , _ ( " Resulting path too long for buffer in qemudInitPaths() " ) ) ;
2007-02-16 18:30:55 +00:00
return - 1 ;
2007-02-14 01:40:09 +00:00
}
2007-06-11 12:04:54 +00:00
static struct qemud_server * qemudInitialize ( int sigread ) {
2007-02-14 01:40:09 +00:00
struct qemud_server * server ;
2008-06-06 10:52:01 +00:00
if ( VIR_ALLOC ( server ) < 0 ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR0 ( _ ( " Failed to allocate struct qemud_server " ) ) ;
2007-02-14 01:40:09 +00:00
return NULL ;
2007-02-16 18:30:55 +00:00
}
2007-02-14 01:40:09 +00:00
2008-12-04 22:16:40 +00:00
if ( pthread_mutex_init ( & server - > lock , NULL ) ! = 0 ) {
VIR_FREE ( server ) ;
return NULL ;
}
2007-02-16 18:28:17 +00:00
server - > sigread = sigread ;
2007-02-14 01:40:09 +00:00
2008-12-04 22:14:15 +00:00
if ( virEventInit ( ) < 0 ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR0 ( _ ( " Failed to initialize event system " ) ) ;
2008-12-04 22:14:15 +00:00
VIR_FREE ( server ) ;
return NULL ;
}
2008-11-17 12:18:18 +00:00
virInitialize ( ) ;
2008-12-02 11:37:55 +00:00
/*
* Note that the order is important : the first ones have a higher
* priority when calling virStateInitialize . We must register
* the network , storage and nodedev drivers before any domain
* drivers , since their resources must be auto - started before
* any domains can be auto - started .
*/
2008-11-21 12:16:08 +00:00
# ifdef WITH_DRIVER_MODULES
/* We don't care if any of these fail, because the whole point
* is to allow users to only install modules they want to use .
* If they try to use a open a connection for a module that
* is not loaded they ' ll get a suitable error at that point
*/
virDriverLoadModule ( " network " ) ;
virDriverLoadModule ( " storage " ) ;
2008-11-21 12:27:11 +00:00
virDriverLoadModule ( " nodedev " ) ;
2008-12-02 11:37:55 +00:00
virDriverLoadModule ( " qemu " ) ;
virDriverLoadModule ( " lxc " ) ;
virDriverLoadModule ( " uml " ) ;
2008-11-21 12:16:08 +00:00
# else
2008-11-17 12:18:18 +00:00
# ifdef WITH_NETWORK
networkRegister ( ) ;
# endif
# ifdef WITH_STORAGE_DIR
storageRegister ( ) ;
2008-11-21 12:16:08 +00:00
# endif
2008-12-18 11:52:06 +00:00
# if defined(WITH_NODE_DEVICES) && \
( defined ( HAVE_HAL ) | | defined ( HAVE_DEVKIT ) )
2008-11-21 12:27:11 +00:00
nodedevRegister ( ) ;
# endif
2008-12-02 11:37:55 +00:00
# ifdef WITH_QEMU
qemuRegister ( ) ;
# endif
# ifdef WITH_LXC
lxcRegister ( ) ;
# endif
# ifdef WITH_UML
umlRegister ( ) ;
# endif
2008-11-17 12:18:18 +00:00
# endif
2008-10-23 13:18:18 +00:00
virEventRegisterImpl ( virEventAddHandleImpl ,
virEventUpdateHandleImpl ,
virEventRemoveHandleImpl ,
virEventAddTimeoutImpl ,
virEventUpdateTimeoutImpl ,
virEventRemoveTimeoutImpl ) ;
2007-06-26 23:48:46 +00:00
2007-06-26 22:56:14 +00:00
virStateInitialize ( ) ;
2007-12-05 15:34:05 +00:00
return server ;
}
static struct qemud_server * qemudNetworkInit ( struct qemud_server * server ) {
struct qemud_socket * sock ;
char sockname [ PATH_MAX ] ;
char roSockname [ PATH_MAX ] ;
2007-12-05 15:24:15 +00:00
# if HAVE_SASL
2007-12-05 15:34:05 +00:00
int err ;
# endif /* HAVE_SASL */
roSockname [ 0 ] = ' \0 ' ;
if ( qemudInitPaths ( server , sockname , roSockname , PATH_MAX ) < 0 )
goto cleanup ;
if ( qemudListenUnix ( server , sockname , 0 , auth_unix_rw ) < 0 )
2007-12-05 15:24:15 +00:00
goto cleanup ;
2007-12-05 15:34:05 +00:00
if ( roSockname [ 0 ] ! = ' \0 ' & & qemudListenUnix ( server , roSockname , 1 , auth_unix_ro ) < 0 )
goto cleanup ;
# if HAVE_SASL
if ( auth_unix_rw = = REMOTE_AUTH_SASL | |
auth_unix_ro = = REMOTE_AUTH_SASL | |
auth_tcp = = REMOTE_AUTH_SASL | |
auth_tls = = REMOTE_AUTH_SASL ) {
if ( ( err = sasl_server_init ( NULL , " libvirt " ) ) ! = SASL_OK ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " Failed to initialize SASL authentication %s " ) ,
sasl_errstring ( err , NULL , NULL ) ) ;
2007-12-05 15:34:05 +00:00
goto cleanup ;
}
2007-12-05 15:24:15 +00:00
}
# endif
2007-12-05 18:21:27 +00:00
# ifdef HAVE_POLKIT
if ( auth_unix_rw = = REMOTE_AUTH_POLKIT | |
auth_unix_ro = = REMOTE_AUTH_POLKIT ) {
DBusError derr ;
dbus_error_init ( & derr ) ;
server - > sysbus = dbus_bus_get ( DBUS_BUS_SYSTEM , & derr ) ;
if ( ! ( server - > sysbus ) ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " Failed to connect to system bus for PolicyKit auth: %s " ) ,
derr . message ) ;
2007-12-05 18:21:27 +00:00
dbus_error_free ( & derr ) ;
goto cleanup ;
}
}
# endif
2007-06-26 23:48:46 +00:00
if ( ipsock ) {
2008-05-14 20:57:20 +00:00
if ( listen_tcp & & remoteListenTCP ( server , listen_addr , tcp_port , QEMUD_SOCK_TYPE_TCP , auth_tcp ) < 0 )
2007-06-11 12:04:54 +00:00
goto cleanup ;
if ( listen_tls ) {
if ( remoteInitializeGnuTLS ( ) < 0 )
goto cleanup ;
2008-05-14 20:57:20 +00:00
if ( remoteListenTCP ( server , listen_addr , tls_port , QEMUD_SOCK_TYPE_TLS , auth_tls ) < 0 )
2007-06-11 12:04:54 +00:00
goto cleanup ;
}
2007-02-14 01:40:09 +00:00
}
2007-09-19 01:56:55 +00:00
# ifdef HAVE_AVAHI
if ( getuid ( ) = = 0 & & mdns_adv ) {
struct libvirtd_mdns_group * group ;
int port = 0 ;
server - > mdns = libvirtd_mdns_new ( ) ;
if ( ! mdns_name ) {
char groupname [ 64 ] , localhost [ HOST_NAME_MAX + 1 ] , * tmp ;
/* Extract the host part of the potentially FQDN */
gethostname ( localhost , HOST_NAME_MAX ) ;
localhost [ HOST_NAME_MAX ] = ' \0 ' ;
if ( ( tmp = strchr ( localhost , ' . ' ) ) )
* tmp = ' \0 ' ;
snprintf ( groupname , sizeof ( groupname ) - 1 , " Virtualization Host %s " , localhost ) ;
groupname [ sizeof ( groupname ) - 1 ] = ' \0 ' ;
group = libvirtd_mdns_add_group ( server - > mdns , groupname ) ;
} else {
group = libvirtd_mdns_add_group ( server - > mdns , mdns_name ) ;
}
Detect heap allocation failure; factor out some duplication.
* qemud/qemud.c (tls_port, tcp_port, mdns_name, tls_allowed_ip_list):
(tls_allowed_dn_list): Remove "const", now that we free these.
(unix_sock_rw_mask): Rename from unix_sock_rw_perms, so that
the latter name can be used as a local string variable, so that the
variable name matches the config attribute name.
(unix_sock_ro_mask): Rename from unix_sock_ro_perms, likewise.
(remoteCheckDN, remoteCheckAccess): Adapt to const removal.
(qemudDispatchServer): Check for heap allocation failure.
(remoteConfigGetStringList): New function, based on code from Dan Berrangé.
(CHECK_TYPE): Remove macro.
(checkType): New function.
(GET_CONF_INT, GET_CONF_STR): New macros.
(remoteReadConfigFile): Use new macros to avoid duplication and to
check for allocation failure.
* src/conf.h (virConfTypeName): New static inline function.
2007-11-30 15:43:42 +00:00
/*
2007-09-19 01:56:55 +00:00
* See if there ' s a TLS enabled port we can advertise . Cowardly
* don ' t bother to advertise TCP since we don ' t want people using
* them for real world apps
*/
sock = server - > sockets ;
while ( sock ) {
2007-12-05 15:27:08 +00:00
if ( sock - > port ! = - 1 & & sock - > type = = QEMUD_SOCK_TYPE_TLS ) {
2007-09-19 01:56:55 +00:00
port = sock - > port ;
break ;
}
sock = sock - > next ;
}
Detect heap allocation failure; factor out some duplication.
* qemud/qemud.c (tls_port, tcp_port, mdns_name, tls_allowed_ip_list):
(tls_allowed_dn_list): Remove "const", now that we free these.
(unix_sock_rw_mask): Rename from unix_sock_rw_perms, so that
the latter name can be used as a local string variable, so that the
variable name matches the config attribute name.
(unix_sock_ro_mask): Rename from unix_sock_ro_perms, likewise.
(remoteCheckDN, remoteCheckAccess): Adapt to const removal.
(qemudDispatchServer): Check for heap allocation failure.
(remoteConfigGetStringList): New function, based on code from Dan Berrangé.
(CHECK_TYPE): Remove macro.
(checkType): New function.
(GET_CONF_INT, GET_CONF_STR): New macros.
(remoteReadConfigFile): Use new macros to avoid duplication and to
check for allocation failure.
* src/conf.h (virConfTypeName): New static inline function.
2007-11-30 15:43:42 +00:00
2007-09-19 01:56:55 +00:00
/*
* Add the primary entry - we choose SSH because its most likely to always
* be available
*/
libvirtd_mdns_add_entry ( group , " _libvirt._tcp " , port ) ;
libvirtd_mdns_start ( server - > mdns ) ;
}
# endif
2007-02-14 01:40:09 +00:00
return server ;
cleanup :
if ( server ) {
2007-09-19 01:56:55 +00:00
sock = server - > sockets ;
2007-02-14 01:40:09 +00:00
while ( sock ) {
close ( sock - > fd ) ;
sock = sock - > next ;
}
2007-12-05 18:21:27 +00:00
# ifdef HAVE_POLKIT
if ( server - > sysbus )
dbus_connection_unref ( server - > sysbus ) ;
# endif
2007-02-14 01:40:09 +00:00
free ( server ) ;
}
return NULL ;
}
2007-06-11 12:04:54 +00:00
static gnutls_session_t
remoteInitializeTLSSession ( void )
{
gnutls_session_t session ;
int err ;
err = gnutls_init ( & session , GNUTLS_SERVER ) ;
if ( err ! = 0 ) goto failed ;
/* avoid calling all the priority functions, since the defaults
* are adequate .
*/
err = gnutls_set_default_priority ( session ) ;
if ( err ! = 0 ) goto failed ;
err = gnutls_credentials_set ( session , GNUTLS_CRD_CERTIFICATE , x509_cred ) ;
if ( err ! = 0 ) goto failed ;
/* request client certificate if any.
*/
gnutls_certificate_server_set_request ( session , GNUTLS_CERT_REQUEST ) ;
gnutls_dh_set_prime_bits ( session , DH_BITS ) ;
return session ;
failed :
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " remoteInitializeTLSSession: %s " ) ,
2007-06-11 12:04:54 +00:00
gnutls_strerror ( err ) ) ;
return NULL ;
}
/* Check DN is on tls_allowed_dn_list. */
static int
remoteCheckDN ( gnutls_x509_crt_t cert )
{
char name [ 256 ] ;
size_t namesize = sizeof name ;
Detect heap allocation failure; factor out some duplication.
* qemud/qemud.c (tls_port, tcp_port, mdns_name, tls_allowed_ip_list):
(tls_allowed_dn_list): Remove "const", now that we free these.
(unix_sock_rw_mask): Rename from unix_sock_rw_perms, so that
the latter name can be used as a local string variable, so that the
variable name matches the config attribute name.
(unix_sock_ro_mask): Rename from unix_sock_ro_perms, likewise.
(remoteCheckDN, remoteCheckAccess): Adapt to const removal.
(qemudDispatchServer): Check for heap allocation failure.
(remoteConfigGetStringList): New function, based on code from Dan Berrangé.
(CHECK_TYPE): Remove macro.
(checkType): New function.
(GET_CONF_INT, GET_CONF_STR): New macros.
(remoteReadConfigFile): Use new macros to avoid duplication and to
check for allocation failure.
* src/conf.h (virConfTypeName): New static inline function.
2007-11-30 15:43:42 +00:00
char * * wildcards ;
2007-06-11 12:04:54 +00:00
int err ;
err = gnutls_x509_crt_get_dn ( cert , name , & namesize ) ;
if ( err ! = 0 ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " remoteCheckDN: gnutls_x509_cert_get_dn: %s " ) ,
2007-06-11 12:04:54 +00:00
gnutls_strerror ( err ) ) ;
return 0 ;
}
/* If the list is not set, allow any DN. */
wildcards = tls_allowed_dn_list ;
if ( ! wildcards )
return 1 ;
while ( * wildcards ) {
if ( fnmatch ( * wildcards , name , 0 ) = = 0 )
return 1 ;
wildcards + + ;
}
/* Print the client's DN. */
2008-12-22 12:53:26 +00:00
DEBUG ( _ ( " remoteCheckDN: failed: client DN is %s " ) , name ) ;
2007-06-11 12:04:54 +00:00
return 0 ; // Not found.
}
static int
remoteCheckCertificate ( gnutls_session_t session )
{
int ret ;
unsigned int status ;
const gnutls_datum_t * certs ;
unsigned int nCerts , i ;
time_t now ;
if ( ( ret = gnutls_certificate_verify_peers2 ( session , & status ) ) < 0 ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " remoteCheckCertificate: verify failed: %s " ) ,
2007-06-11 12:04:54 +00:00
gnutls_strerror ( ret ) ) ;
return - 1 ;
}
if ( status ! = 0 ) {
if ( status & GNUTLS_CERT_INVALID )
2009-01-06 18:32:03 +00:00
VIR_ERROR0 ( _ ( " remoteCheckCertificate: "
" the client certificate is not trusted. " ) ) ;
2007-06-11 12:04:54 +00:00
if ( status & GNUTLS_CERT_SIGNER_NOT_FOUND )
2009-01-06 18:32:03 +00:00
VIR_ERROR0 ( _ ( " remoteCheckCertificate: the client "
" certificate has unknown issuer. " ) ) ;
2007-06-11 12:04:54 +00:00
if ( status & GNUTLS_CERT_REVOKED )
2009-01-06 18:32:03 +00:00
VIR_ERROR0 ( _ ( " remoteCheckCertificate: "
" the client certificate has been revoked. " ) ) ;
2007-06-11 12:04:54 +00:00
2007-08-07 13:02:35 +00:00
# ifndef GNUTLS_1_0_COMPAT
2007-06-11 12:04:54 +00:00
if ( status & GNUTLS_CERT_INSECURE_ALGORITHM )
2009-01-06 18:32:03 +00:00
VIR_ERROR0 ( _ ( " remoteCheckCertificate: the client certificate "
" uses an insecure algorithm. " ) ) ;
2007-08-07 13:02:35 +00:00
# endif
2007-06-11 12:04:54 +00:00
return - 1 ;
}
if ( gnutls_certificate_type_get ( session ) ! = GNUTLS_CRT_X509 ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR0 ( _ ( " remoteCheckCertificate: certificate is not X.509 " ) ) ;
2007-06-11 12:04:54 +00:00
return - 1 ;
}
if ( ! ( certs = gnutls_certificate_get_peers ( session , & nCerts ) ) ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR0 ( _ ( " remoteCheckCertificate: no peers " ) ) ;
2007-06-11 12:04:54 +00:00
return - 1 ;
}
now = time ( NULL ) ;
for ( i = 0 ; i < nCerts ; i + + ) {
gnutls_x509_crt_t cert ;
if ( gnutls_x509_crt_init ( & cert ) < 0 ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR0 ( _ ( " remoteCheckCertificate: gnutls_x509_crt_init failed " ) ) ;
2007-06-11 12:04:54 +00:00
return - 1 ;
}
if ( gnutls_x509_crt_import ( cert , & certs [ i ] , GNUTLS_X509_FMT_DER ) < 0 ) {
gnutls_x509_crt_deinit ( cert ) ;
return - 1 ;
}
Detect heap allocation failure; factor out some duplication.
* qemud/qemud.c (tls_port, tcp_port, mdns_name, tls_allowed_ip_list):
(tls_allowed_dn_list): Remove "const", now that we free these.
(unix_sock_rw_mask): Rename from unix_sock_rw_perms, so that
the latter name can be used as a local string variable, so that the
variable name matches the config attribute name.
(unix_sock_ro_mask): Rename from unix_sock_ro_perms, likewise.
(remoteCheckDN, remoteCheckAccess): Adapt to const removal.
(qemudDispatchServer): Check for heap allocation failure.
(remoteConfigGetStringList): New function, based on code from Dan Berrangé.
(CHECK_TYPE): Remove macro.
(checkType): New function.
(GET_CONF_INT, GET_CONF_STR): New macros.
(remoteReadConfigFile): Use new macros to avoid duplication and to
check for allocation failure.
* src/conf.h (virConfTypeName): New static inline function.
2007-11-30 15:43:42 +00:00
2007-06-11 12:04:54 +00:00
if ( gnutls_x509_crt_get_expiration_time ( cert ) < now ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR0 ( _ ( " remoteCheckCertificate: "
" the client certificate has expired " ) ) ;
2007-06-11 12:04:54 +00:00
gnutls_x509_crt_deinit ( cert ) ;
return - 1 ;
}
Detect heap allocation failure; factor out some duplication.
* qemud/qemud.c (tls_port, tcp_port, mdns_name, tls_allowed_ip_list):
(tls_allowed_dn_list): Remove "const", now that we free these.
(unix_sock_rw_mask): Rename from unix_sock_rw_perms, so that
the latter name can be used as a local string variable, so that the
variable name matches the config attribute name.
(unix_sock_ro_mask): Rename from unix_sock_ro_perms, likewise.
(remoteCheckDN, remoteCheckAccess): Adapt to const removal.
(qemudDispatchServer): Check for heap allocation failure.
(remoteConfigGetStringList): New function, based on code from Dan Berrangé.
(CHECK_TYPE): Remove macro.
(checkType): New function.
(GET_CONF_INT, GET_CONF_STR): New macros.
(remoteReadConfigFile): Use new macros to avoid duplication and to
check for allocation failure.
* src/conf.h (virConfTypeName): New static inline function.
2007-11-30 15:43:42 +00:00
2007-06-11 12:04:54 +00:00
if ( gnutls_x509_crt_get_activation_time ( cert ) > now ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR0 ( _ ( " remoteCheckCertificate: the client "
" certificate is not yet activated " ) ) ;
2007-06-11 12:04:54 +00:00
gnutls_x509_crt_deinit ( cert ) ;
return - 1 ;
}
if ( i = = 0 ) {
if ( ! remoteCheckDN ( cert ) ) {
/* This is the most common error: make it informative. */
2009-01-06 18:32:03 +00:00
VIR_ERROR0 ( _ ( " remoteCheckCertificate: client's Distinguished Name is not on the list of allowed clients (tls_allowed_dn_list). Use 'openssl x509 -in clientcert.pem -text' to view the Distinguished Name field in the client certificate, or run this daemon with --verbose option. " ) ) ;
2007-06-11 12:04:54 +00:00
gnutls_x509_crt_deinit ( cert ) ;
return - 1 ;
}
}
}
return 0 ;
}
/* Check the client's access. */
static int
remoteCheckAccess ( struct qemud_client * client )
{
/* Verify client certificate. */
2007-12-05 15:27:08 +00:00
if ( remoteCheckCertificate ( client - > tlssession ) = = - 1 ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR0 ( _ ( " remoteCheckCertificate: "
" failed to verify client's certificate " ) ) ;
2007-06-11 12:04:54 +00:00
if ( ! tls_no_verify_certificate ) return - 1 ;
2009-01-06 18:32:03 +00:00
else VIR_INFO0 ( _ ( " remoteCheckCertificate: tls_no_verify_certificate "
" is set so the bad certificate is ignored " ) ) ;
2007-06-11 12:04:54 +00:00
}
/* Checks have succeeded. Write a '\1' byte back to the client to
* indicate this ( otherwise the socket is abruptly closed ) .
* ( NB . The ' \1 ' byte is sent in an encrypted record ) .
*/
client - > bufferLength = 1 ;
client - > bufferOffset = 0 ;
client - > buffer [ 0 ] = ' \1 ' ;
client - > mode = QEMUD_MODE_TX_PACKET ;
return 0 ;
}
2007-02-14 01:40:09 +00:00
2008-04-04 15:09:19 +00:00
# if HAVE_POLKIT
int qemudGetSocketIdentity ( int fd , uid_t * uid , pid_t * pid ) {
# ifdef SO_PEERCRED
struct ucred cr ;
unsigned int cr_len = sizeof ( cr ) ;
if ( getsockopt ( fd , SOL_SOCKET , SO_PEERCRED , & cr , & cr_len ) < 0 ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " Failed to verify client credentials: %s " ) ,
strerror ( errno ) ) ;
2008-04-04 15:09:19 +00:00
return - 1 ;
}
* pid = cr . pid ;
* uid = cr . uid ;
# else
/* XXX Many more OS support UNIX socket credentials we could port to. See dbus ....*/
# error "UNIX socket credentials not supported / implemented on this platform yet..."
# endif
return 0 ;
}
# endif
2007-02-14 01:40:09 +00:00
static int qemudDispatchServer ( struct qemud_server * server , struct qemud_socket * sock ) {
int fd ;
struct sockaddr_storage addr ;
2007-06-11 12:04:54 +00:00
socklen_t addrlen = ( socklen_t ) ( sizeof addr ) ;
2007-02-14 01:40:09 +00:00
struct qemud_client * client ;
2007-06-11 12:04:54 +00:00
int no_slow_start = 1 ;
2007-02-14 01:40:09 +00:00
if ( ( fd = accept ( sock - > fd , ( struct sockaddr * ) & addr , & addrlen ) ) < 0 ) {
if ( errno = = EAGAIN )
return 0 ;
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " Failed to accept connection: %s " ) , strerror ( errno ) ) ;
2007-02-14 01:40:09 +00:00
return - 1 ;
}
2008-12-04 22:18:44 +00:00
if ( server - > nclients > = max_clients ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR0 ( _ ( " Too many active clients, dropping connection " ) ) ;
2008-12-04 22:18:44 +00:00
close ( fd ) ;
return - 1 ;
}
2008-12-04 22:09:35 +00:00
if ( VIR_REALLOC_N ( server - > clients , server - > nclients + 1 ) < 0 ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR0 ( _ ( " Out of memory allocating clients " ) ) ;
2008-12-04 22:09:35 +00:00
close ( fd ) ;
return - 1 ;
}
2007-06-11 12:04:54 +00:00
/* Disable Nagle. Unix sockets will ignore this. */
setsockopt ( fd , IPPROTO_TCP , TCP_NODELAY , ( void * ) & no_slow_start ,
sizeof no_slow_start ) ;
2007-02-16 18:30:55 +00:00
if ( qemudSetCloseExec ( fd ) < 0 | |
qemudSetNonBlock ( fd ) < 0 ) {
2007-02-14 01:40:09 +00:00
close ( fd ) ;
return - 1 ;
}
2008-06-06 10:52:01 +00:00
if ( VIR_ALLOC ( client ) < 0 )
Detect heap allocation failure; factor out some duplication.
* qemud/qemud.c (tls_port, tcp_port, mdns_name, tls_allowed_ip_list):
(tls_allowed_dn_list): Remove "const", now that we free these.
(unix_sock_rw_mask): Rename from unix_sock_rw_perms, so that
the latter name can be used as a local string variable, so that the
variable name matches the config attribute name.
(unix_sock_ro_mask): Rename from unix_sock_ro_perms, likewise.
(remoteCheckDN, remoteCheckAccess): Adapt to const removal.
(qemudDispatchServer): Check for heap allocation failure.
(remoteConfigGetStringList): New function, based on code from Dan Berrangé.
(CHECK_TYPE): Remove macro.
(checkType): New function.
(GET_CONF_INT, GET_CONF_STR): New macros.
(remoteReadConfigFile): Use new macros to avoid duplication and to
check for allocation failure.
* src/conf.h (virConfTypeName): New static inline function.
2007-11-30 15:43:42 +00:00
goto cleanup ;
2008-12-04 22:16:40 +00:00
if ( pthread_mutex_init ( & client - > lock , NULL ) ! = 0 )
goto cleanup ;
2007-06-11 12:04:54 +00:00
client - > magic = QEMUD_CLIENT_MAGIC ;
2007-02-14 01:40:09 +00:00
client - > fd = fd ;
client - > readonly = sock - > readonly ;
2007-12-05 15:27:08 +00:00
client - > type = sock - > type ;
2007-12-05 15:24:15 +00:00
client - > auth = sock - > auth ;
2007-06-11 12:04:54 +00:00
memcpy ( & client - > addr , & addr , sizeof addr ) ;
client - > addrlen = addrlen ;
2008-10-23 13:18:18 +00:00
client - > server = server ;
2007-06-11 12:04:54 +00:00
2008-04-04 15:09:19 +00:00
# if HAVE_POLKIT
/* Only do policy checks for non-root - allow root user
through with no checks , as a fail - safe - root can easily
change policykit policy anyway , so its pointless trying
to restrict root */
if ( client - > auth = = REMOTE_AUTH_POLKIT ) {
uid_t uid ;
pid_t pid ;
if ( qemudGetSocketIdentity ( client - > fd , & uid , & pid ) < 0 )
goto cleanup ;
2008-05-15 06:12:32 +00:00
/* Client is running as root, so disable auth */
2008-04-04 15:09:19 +00:00
if ( uid = = 0 ) {
2009-01-06 18:32:03 +00:00
VIR_INFO ( _ ( " Turn off polkit auth for privileged client %d " ) , pid ) ;
2008-04-04 15:09:19 +00:00
client - > auth = REMOTE_AUTH_NONE ;
}
}
# endif
2007-12-05 15:27:08 +00:00
if ( client - > type ! = QEMUD_SOCK_TYPE_TLS ) {
2007-06-11 12:04:54 +00:00
client - > mode = QEMUD_MODE_RX_HEADER ;
2007-11-17 11:17:48 +00:00
client - > bufferLength = REMOTE_MESSAGE_HEADER_XDR_LEN ;
2007-06-26 19:11:00 +00:00
if ( qemudRegisterClientEvent ( server , client , 0 ) < 0 )
goto cleanup ;
2007-06-11 12:04:54 +00:00
} else {
int ret ;
2007-12-05 15:27:08 +00:00
client - > tlssession = remoteInitializeTLSSession ( ) ;
if ( client - > tlssession = = NULL )
2007-06-26 19:11:00 +00:00
goto cleanup ;
2007-06-11 12:04:54 +00:00
2007-12-05 15:27:08 +00:00
gnutls_transport_set_ptr ( client - > tlssession ,
2007-06-11 12:04:54 +00:00
( gnutls_transport_ptr_t ) ( long ) fd ) ;
/* Begin the TLS handshake. */
2007-12-05 15:27:08 +00:00
ret = gnutls_handshake ( client - > tlssession ) ;
2007-06-11 12:04:54 +00:00
if ( ret = = 0 ) {
/* Unlikely, but ... Next step is to check the certificate. */
if ( remoteCheckAccess ( client ) = = - 1 )
2007-06-26 19:11:00 +00:00
goto cleanup ;
if ( qemudRegisterClientEvent ( server , client , 0 ) < 0 )
goto cleanup ;
2007-06-11 12:04:54 +00:00
} else if ( ret = = GNUTLS_E_INTERRUPTED | | ret = = GNUTLS_E_AGAIN ) {
/* Most likely. */
client - > mode = QEMUD_MODE_TLS_HANDSHAKE ;
client - > bufferLength = - 1 ;
2007-06-26 19:11:00 +00:00
if ( qemudRegisterClientEvent ( server , client , 0 ) < 0 )
goto cleanup ;
2007-06-11 12:04:54 +00:00
} else {
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " TLS handshake failed: %s " ) ,
2007-06-11 12:04:54 +00:00
gnutls_strerror ( ret ) ) ;
2007-06-26 19:11:00 +00:00
goto cleanup ;
2007-06-11 12:04:54 +00:00
}
}
2007-02-14 01:40:09 +00:00
2008-12-04 22:09:35 +00:00
server - > clients [ server - > nclients + + ] = client ;
2007-02-14 01:40:09 +00:00
return 0 ;
2007-06-11 12:04:54 +00:00
2007-06-26 19:11:00 +00:00
cleanup :
2008-12-04 22:16:40 +00:00
if ( client & &
client - > tlssession ) gnutls_deinit ( client - > tlssession ) ;
2007-06-11 12:04:54 +00:00
close ( fd ) ;
free ( client ) ;
return - 1 ;
2007-02-14 01:40:09 +00:00
}
2008-12-04 22:16:40 +00:00
/*
* You must hold lock for at least the client
* We don ' t free stuff here , merely disconnect the client ' s
* network socket & resources .
* We keep the libvirt connection open until any async
* jobs have finished , then clean it up elsehwere
*/
static void qemudDispatchClientFailure ( struct qemud_server * server ATTRIBUTE_UNUSED ,
struct qemud_client * client ) {
2008-11-19 16:19:36 +00:00
virEventRemoveHandleImpl ( client - > watch ) ;
2007-06-26 19:11:00 +00:00
2008-10-23 13:18:18 +00:00
/* Deregister event delivery callback */
if ( client - > conn ) {
2008-12-22 12:53:26 +00:00
DEBUG0 ( " Deregistering to relay remote events " ) ;
2008-10-23 13:18:18 +00:00
virConnectDomainEventDeregister ( client - > conn , remoteRelayDomainEvent ) ;
}
2007-12-05 15:24:15 +00:00
# if HAVE_SASL
if ( client - > saslconn ) sasl_dispose ( & client - > saslconn ) ;
2008-01-29 17:41:07 +00:00
free ( client - > saslUsername ) ;
2007-12-05 15:24:15 +00:00
# endif
2007-12-05 15:27:08 +00:00
if ( client - > tlssession ) gnutls_deinit ( client - > tlssession ) ;
2007-02-14 01:40:09 +00:00
close ( client - > fd ) ;
2008-12-04 22:16:40 +00:00
client - > fd = - 1 ;
}
/* Caller must hold server lock */
static struct qemud_client * qemudPendingJob ( struct qemud_server * server )
{
int i ;
for ( i = 0 ; i < server - > nclients ; i + + ) {
pthread_mutex_lock ( & server - > clients [ i ] - > lock ) ;
if ( server - > clients [ i ] - > mode = = QEMUD_MODE_WAIT_DISPATCH ) {
/* Delibrately don't unlock client - caller wants the lock */
return server - > clients [ i ] ;
}
pthread_mutex_unlock ( & server - > clients [ i ] - > lock ) ;
}
return NULL ;
2007-02-14 01:40:09 +00:00
}
2008-12-04 22:16:40 +00:00
static void * qemudWorker ( void * data )
{
struct qemud_server * server = data ;
while ( 1 ) {
struct qemud_client * client ;
int len ;
pthread_mutex_lock ( & server - > lock ) ;
while ( ( client = qemudPendingJob ( server ) ) = = NULL )
pthread_cond_wait ( & server - > job , & server - > lock ) ;
pthread_mutex_unlock ( & server - > lock ) ;
/* We own a locked client now... */
client - > mode = QEMUD_MODE_IN_DISPATCH ;
client - > refs + + ;
if ( ( len = remoteDispatchClientRequest ( server , client ) ) = = 0 )
qemudDispatchClientFailure ( server , client ) ;
/* Set up the output buffer. */
client - > mode = QEMUD_MODE_TX_PACKET ;
client - > bufferLength = len ;
client - > bufferOffset = 0 ;
if ( qemudRegisterClientEvent ( server , client , 1 ) < 0 )
qemudDispatchClientFailure ( server , client ) ;
client - > refs - - ;
pthread_mutex_unlock ( & client - > lock ) ;
pthread_mutex_unlock ( & server - > lock ) ;
}
}
2007-02-14 01:40:09 +00:00
2007-12-05 15:27:08 +00:00
static int qemudClientReadBuf ( struct qemud_server * server ,
struct qemud_client * client ,
char * data , unsigned len ) {
int ret ;
2007-06-11 12:04:54 +00:00
/*qemudDebug ("qemudClientRead: len = %d", len);*/
2007-12-05 15:27:08 +00:00
if ( ! client - > tlssession ) {
2007-06-11 12:04:54 +00:00
if ( ( ret = read ( client - > fd , data , len ) ) < = 0 ) {
if ( ret = = 0 | | errno ! = EAGAIN ) {
if ( ret ! = 0 )
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " read: %s " ) , strerror ( errno ) ) ;
2007-06-11 12:04:54 +00:00
qemudDispatchClientFailure ( server , client ) ;
}
return - 1 ;
}
} else {
2007-12-05 15:27:08 +00:00
ret = gnutls_record_recv ( client - > tlssession , data , len ) ;
2007-06-26 19:11:00 +00:00
if ( qemudRegisterClientEvent ( server , client , 1 ) < 0 )
qemudDispatchClientFailure ( server , client ) ;
2007-07-12 15:04:05 +00:00
else if ( ret < = 0 ) {
2007-06-11 12:04:54 +00:00
if ( ret = = 0 | | ( ret ! = GNUTLS_E_AGAIN & &
ret ! = GNUTLS_E_INTERRUPTED ) ) {
if ( ret ! = 0 )
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " gnutls_record_recv: %s " ) ,
2007-06-11 12:04:54 +00:00
gnutls_strerror ( ret ) ) ;
qemudDispatchClientFailure ( server , client ) ;
}
return - 1 ;
}
2007-02-14 01:40:09 +00:00
}
2007-06-11 12:04:54 +00:00
2007-12-05 15:27:08 +00:00
return ret ;
}
static int qemudClientReadPlain ( struct qemud_server * server ,
struct qemud_client * client ) {
int ret ;
ret = qemudClientReadBuf ( server , client ,
client - > buffer + client - > bufferOffset ,
client - > bufferLength - client - > bufferOffset ) ;
if ( ret < 0 )
return ret ;
2007-06-11 12:04:54 +00:00
client - > bufferOffset + = ret ;
return 0 ;
2007-02-14 01:40:09 +00:00
}
2007-12-05 15:27:08 +00:00
# if HAVE_SASL
static int qemudClientReadSASL ( struct qemud_server * server ,
struct qemud_client * client ) {
int got , want ;
/* We're doing a SSF data read, so now its times to ensure
* future writes are under SSF too .
*
* cf remoteSASLCheckSSF in remote . c
*/
client - > saslSSF | = QEMUD_SASL_SSF_WRITE ;
/* Need to read some more data off the wire */
if ( client - > saslDecoded = = NULL ) {
char encoded [ 8192 ] ;
int encodedLen = sizeof ( encoded ) ;
encodedLen = qemudClientReadBuf ( server , client , encoded , encodedLen ) ;
if ( encodedLen < 0 )
return - 1 ;
sasl_decode ( client - > saslconn , encoded , encodedLen ,
& client - > saslDecoded , & client - > saslDecodedLength ) ;
client - > saslDecodedOffset = 0 ;
}
/* Some buffered decoded data to return now */
got = client - > saslDecodedLength - client - > saslDecodedOffset ;
want = client - > bufferLength - client - > bufferOffset ;
if ( want > got )
want = got ;
memcpy ( client - > buffer + client - > bufferOffset ,
client - > saslDecoded + client - > saslDecodedOffset , want ) ;
client - > saslDecodedOffset + = want ;
client - > bufferOffset + = want ;
if ( client - > saslDecodedOffset = = client - > saslDecodedLength ) {
client - > saslDecoded = NULL ;
client - > saslDecodedOffset = client - > saslDecodedLength = 0 ;
}
return 0 ;
}
# endif
static int qemudClientRead ( struct qemud_server * server ,
struct qemud_client * client ) {
# if HAVE_SASL
if ( client - > saslSSF & QEMUD_SASL_SSF_READ )
return qemudClientReadSASL ( server , client ) ;
else
# endif
return qemudClientReadPlain ( server , client ) ;
}
2007-02-14 01:40:09 +00:00
static void qemudDispatchClientRead ( struct qemud_server * server , struct qemud_client * client ) {
2008-12-04 22:12:53 +00:00
unsigned int len ;
2007-06-11 12:04:54 +00:00
/*qemudDebug ("qemudDispatchClientRead: mode = %d", client->mode);*/
2007-02-14 01:40:09 +00:00
2007-06-11 12:04:54 +00:00
switch ( client - > mode ) {
case QEMUD_MODE_RX_HEADER : {
XDR x ;
if ( qemudClientRead ( server , client ) < 0 )
return ; /* Error, or blocking */
if ( client - > bufferOffset < client - > bufferLength )
return ; /* Not read enough */
xdrmem_create ( & x , client - > buffer , client - > bufferLength , XDR_DECODE ) ;
2007-11-17 11:17:48 +00:00
if ( ! xdr_u_int ( & x , & len ) ) {
xdr_destroy ( & x ) ;
2008-12-22 12:53:26 +00:00
DEBUG0 ( " Failed to decode packet length " ) ;
2007-02-14 01:40:09 +00:00
qemudDispatchClientFailure ( server , client ) ;
return ;
}
2007-11-17 11:17:48 +00:00
xdr_destroy ( & x ) ;
2007-06-11 12:04:54 +00:00
2007-11-17 11:17:48 +00:00
if ( len > REMOTE_MESSAGE_MAX ) {
2008-12-22 12:53:26 +00:00
DEBUG ( " Packet length %u too large " , len ) ;
2007-06-11 12:04:54 +00:00
qemudDispatchClientFailure ( server , client ) ;
return ;
2007-02-14 01:40:09 +00:00
}
2007-06-11 12:04:54 +00:00
2007-11-17 11:17:48 +00:00
/* Length include length of the length field itself, so
* check minimum size requirements */
if ( len < = REMOTE_MESSAGE_HEADER_XDR_LEN ) {
2008-12-22 12:53:26 +00:00
DEBUG ( " Packet length %u too small " , len ) ;
2007-06-11 12:04:54 +00:00
qemudDispatchClientFailure ( server , client ) ;
return ;
}
client - > mode = QEMUD_MODE_RX_PAYLOAD ;
2007-11-17 11:17:48 +00:00
client - > bufferLength = len - REMOTE_MESSAGE_HEADER_XDR_LEN ;
client - > bufferOffset = 0 ;
2007-06-11 12:04:54 +00:00
2007-06-26 19:11:00 +00:00
if ( qemudRegisterClientEvent ( server , client , 1 ) < 0 ) {
qemudDispatchClientFailure ( server , client ) ;
return ;
}
2007-06-11 12:04:54 +00:00
/* Fall through */
2007-02-14 01:40:09 +00:00
}
2007-06-11 12:04:54 +00:00
case QEMUD_MODE_RX_PAYLOAD : {
if ( qemudClientRead ( server , client ) < 0 )
return ; /* Error, or blocking */
if ( client - > bufferOffset < client - > bufferLength )
return ; /* Not read enough */
2008-12-04 22:16:40 +00:00
client - > mode = QEMUD_MODE_WAIT_DISPATCH ;
2007-11-17 11:17:48 +00:00
if ( qemudRegisterClientEvent ( server , client , 1 ) < 0 )
2007-06-11 12:04:54 +00:00
qemudDispatchClientFailure ( server , client ) ;
2008-12-04 22:16:40 +00:00
pthread_cond_signal ( & server - > job ) ;
2007-06-11 12:04:54 +00:00
break ;
}
case QEMUD_MODE_TLS_HANDSHAKE : {
int ret ;
/* Continue the handshake. */
2007-12-05 15:27:08 +00:00
ret = gnutls_handshake ( client - > tlssession ) ;
2007-06-11 12:04:54 +00:00
if ( ret = = 0 ) {
/* Finished. Next step is to check the certificate. */
if ( remoteCheckAccess ( client ) = = - 1 )
qemudDispatchClientFailure ( server , client ) ;
2007-07-12 15:04:05 +00:00
else if ( qemudRegisterClientEvent ( server , client , 1 ) < 0 )
2007-06-26 19:11:00 +00:00
qemudDispatchClientFailure ( server , client ) ;
2007-06-11 12:04:54 +00:00
} else if ( ret ! = GNUTLS_E_AGAIN & & ret ! = GNUTLS_E_INTERRUPTED ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " TLS handshake failed: %s " ) ,
2007-06-11 12:04:54 +00:00
gnutls_strerror ( ret ) ) ;
qemudDispatchClientFailure ( server , client ) ;
2007-06-26 19:11:00 +00:00
} else {
if ( qemudRegisterClientEvent ( server , client , 1 ) < 0 )
qemudDispatchClientFailure ( server , client ) ;
}
2007-06-11 12:04:54 +00:00
break ;
}
default :
2008-12-22 12:53:26 +00:00
DEBUG ( " Got unexpected data read while in %d mode " , client - > mode ) ;
2007-06-11 12:04:54 +00:00
qemudDispatchClientFailure ( server , client ) ;
2007-02-14 01:40:09 +00:00
}
}
2007-12-05 15:27:08 +00:00
static int qemudClientWriteBuf ( struct qemud_server * server ,
struct qemud_client * client ,
const char * data , int len ) {
int ret ;
if ( ! client - > tlssession ) {
Use safewrite in place of write, in many cases.
Also add "make syntax-check" rules to ensure no new uses sneak in.
There are many uses of write like this:
if (write (fd, xml, towrite) != towrite)
return -1;
The problem is that the syscall can succeed, yet write less than
the requested number of bytes, so the caller should retry
rather than simply failing.
This patch changes most of them to use util.c's safewrite wrapper,
which encapsulates the process. Also, there were a few cases in
which the retry loop was open-coded, and I replaced those, too.
* Makefile.maint (sc_avoid_write): New rule, to avoid recurrence.
* .x-sc_avoid_write: New file. Record two legitimate exemptions.
* qemud/qemud.c (sig_handler, qemudClientWriteBuf): Use safewrite, not write.
* src/conf.c (__virConfWriteFile): Likewise.
* src/qemu_conf.c (qemudSaveConfig, qemudSaveNetworkConfig): Likewise.
* src/qemu_driver.c (qemudWaitForMonitor, qemudStartVMDaemon)
(qemudVMData, PROC_IP_FORWARD): Likewise.
* proxy/libvirt_proxy.c: Include "util.h".
(proxyWriteClientSocket): Use safewrite.
* src/test.c (testDomainSave, testDomainCoreDump): Likewise.
* src/proxy_internal.c (virProxyWriteClientSocket): Likewise.
* src/virsh.c: Include "util-lib.h".
(vshOutputLogFile): Use safewrite.
* src/console.c: Include "util-lib.h".
(vshRunConsole): Use safewrite.
2008-02-22 15:55:04 +00:00
if ( ( ret = safewrite ( client - > fd , data , len ) ) = = - 1 ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " write: %s " ) , strerror ( errno ) ) ;
Use safewrite in place of write, in many cases.
Also add "make syntax-check" rules to ensure no new uses sneak in.
There are many uses of write like this:
if (write (fd, xml, towrite) != towrite)
return -1;
The problem is that the syscall can succeed, yet write less than
the requested number of bytes, so the caller should retry
rather than simply failing.
This patch changes most of them to use util.c's safewrite wrapper,
which encapsulates the process. Also, there were a few cases in
which the retry loop was open-coded, and I replaced those, too.
* Makefile.maint (sc_avoid_write): New rule, to avoid recurrence.
* .x-sc_avoid_write: New file. Record two legitimate exemptions.
* qemud/qemud.c (sig_handler, qemudClientWriteBuf): Use safewrite, not write.
* src/conf.c (__virConfWriteFile): Likewise.
* src/qemu_conf.c (qemudSaveConfig, qemudSaveNetworkConfig): Likewise.
* src/qemu_driver.c (qemudWaitForMonitor, qemudStartVMDaemon)
(qemudVMData, PROC_IP_FORWARD): Likewise.
* proxy/libvirt_proxy.c: Include "util.h".
(proxyWriteClientSocket): Use safewrite.
* src/test.c (testDomainSave, testDomainCoreDump): Likewise.
* src/proxy_internal.c (virProxyWriteClientSocket): Likewise.
* src/virsh.c: Include "util-lib.h".
(vshOutputLogFile): Use safewrite.
* src/console.c: Include "util-lib.h".
(vshRunConsole): Use safewrite.
2008-02-22 15:55:04 +00:00
qemudDispatchClientFailure ( server , client ) ;
2007-06-11 12:04:54 +00:00
return - 1 ;
}
} else {
2007-12-05 15:27:08 +00:00
ret = gnutls_record_send ( client - > tlssession , data , len ) ;
2007-06-26 19:11:00 +00:00
if ( qemudRegisterClientEvent ( server , client , 1 ) < 0 )
qemudDispatchClientFailure ( server , client ) ;
2007-07-12 15:04:05 +00:00
else if ( ret < 0 ) {
2007-06-11 12:04:54 +00:00
if ( ret ! = GNUTLS_E_INTERRUPTED & & ret ! = GNUTLS_E_AGAIN ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " gnutls_record_send: %s " ) , gnutls_strerror ( ret ) ) ;
2007-06-11 12:04:54 +00:00
qemudDispatchClientFailure ( server , client ) ;
}
return - 1 ;
}
2007-02-14 01:40:09 +00:00
}
2007-12-05 15:27:08 +00:00
return ret ;
}
2007-06-11 12:04:54 +00:00
2007-12-05 15:27:08 +00:00
static int qemudClientWritePlain ( struct qemud_server * server ,
struct qemud_client * client ) {
int ret = qemudClientWriteBuf ( server , client ,
client - > buffer + client - > bufferOffset ,
client - > bufferLength - client - > bufferOffset ) ;
if ( ret < 0 )
return - 1 ;
2007-06-11 12:04:54 +00:00
client - > bufferOffset + = ret ;
return 0 ;
2007-02-14 01:40:09 +00:00
}
2007-12-05 15:27:08 +00:00
# if HAVE_SASL
static int qemudClientWriteSASL ( struct qemud_server * server ,
struct qemud_client * client ) {
int ret ;
/* Not got any pending encoded data, so we need to encode raw stuff */
if ( client - > saslEncoded = = NULL ) {
int err ;
err = sasl_encode ( client - > saslconn ,
client - > buffer + client - > bufferOffset ,
client - > bufferLength - client - > bufferOffset ,
& client - > saslEncoded ,
& client - > saslEncodedLength ) ;
client - > saslEncodedOffset = 0 ;
}
/* Send some of the encoded stuff out on the wire */
ret = qemudClientWriteBuf ( server , client ,
client - > saslEncoded + client - > saslEncodedOffset ,
client - > saslEncodedLength - client - > saslEncodedOffset ) ;
if ( ret < 0 )
return - 1 ;
/* Note how much we sent */
client - > saslEncodedOffset + = ret ;
/* Sent all encoded, so update raw buffer to indicate completion */
if ( client - > saslEncodedOffset = = client - > saslEncodedLength ) {
client - > saslEncoded = NULL ;
client - > saslEncodedOffset = client - > saslEncodedLength = 0 ;
client - > bufferOffset = client - > bufferLength ;
}
return 0 ;
}
# endif
static int qemudClientWrite ( struct qemud_server * server ,
struct qemud_client * client ) {
# if HAVE_SASL
if ( client - > saslSSF & QEMUD_SASL_SSF_WRITE )
return qemudClientWriteSASL ( server , client ) ;
else
# endif
return qemudClientWritePlain ( server , client ) ;
}
2008-10-23 13:18:18 +00:00
void
qemudDispatchClientWrite ( struct qemud_server * server ,
struct qemud_client * client ) {
2007-06-11 12:04:54 +00:00
switch ( client - > mode ) {
case QEMUD_MODE_TX_PACKET : {
if ( qemudClientWrite ( server , client ) < 0 )
return ;
if ( client - > bufferOffset = = client - > bufferLength ) {
2008-12-04 22:16:40 +00:00
if ( client - > closing ) {
2007-06-26 19:11:00 +00:00
qemudDispatchClientFailure ( server , client ) ;
2008-12-04 22:16:40 +00:00
} else {
/* Done writing, switch back to receive */
client - > mode = QEMUD_MODE_RX_HEADER ;
client - > bufferLength = REMOTE_MESSAGE_HEADER_XDR_LEN ;
client - > bufferOffset = 0 ;
if ( qemudRegisterClientEvent ( server , client , 1 ) < 0 )
qemudDispatchClientFailure ( server , client ) ;
}
2007-06-11 12:04:54 +00:00
}
/* Still writing */
break ;
}
case QEMUD_MODE_TLS_HANDSHAKE : {
int ret ;
/* Continue the handshake. */
2007-12-05 15:27:08 +00:00
ret = gnutls_handshake ( client - > tlssession ) ;
2007-06-11 12:04:54 +00:00
if ( ret = = 0 ) {
/* Finished. Next step is to check the certificate. */
if ( remoteCheckAccess ( client ) = = - 1 )
qemudDispatchClientFailure ( server , client ) ;
2007-07-12 15:04:05 +00:00
else if ( qemudRegisterClientEvent ( server , client , 1 ) )
2007-06-26 19:11:00 +00:00
qemudDispatchClientFailure ( server , client ) ;
2007-06-11 12:04:54 +00:00
} else if ( ret ! = GNUTLS_E_AGAIN & & ret ! = GNUTLS_E_INTERRUPTED ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " TLS handshake failed: %s " ) , gnutls_strerror ( ret ) ) ;
2007-06-11 12:04:54 +00:00
qemudDispatchClientFailure ( server , client ) ;
2007-06-26 19:11:00 +00:00
} else {
if ( qemudRegisterClientEvent ( server , client , 1 ) )
qemudDispatchClientFailure ( server , client ) ;
}
2007-06-11 12:04:54 +00:00
break ;
}
default :
2008-12-22 12:53:26 +00:00
DEBUG ( " Got unexpected data write while in %d mode " , client - > mode ) ;
2007-06-11 12:04:54 +00:00
qemudDispatchClientFailure ( server , client ) ;
2007-02-14 01:40:09 +00:00
}
}
2007-06-26 19:11:00 +00:00
2008-10-23 13:18:18 +00:00
static void
2008-11-19 16:19:36 +00:00
qemudDispatchClientEvent ( int watch , int fd , int events , void * opaque ) {
2007-06-26 19:11:00 +00:00
struct qemud_server * server = ( struct qemud_server * ) opaque ;
2008-12-04 22:09:35 +00:00
struct qemud_client * client = NULL ;
int i ;
2007-02-23 08:39:49 +00:00
2008-12-04 22:16:40 +00:00
pthread_mutex_lock ( & server - > lock ) ;
2008-12-04 22:09:35 +00:00
for ( i = 0 ; i < server - > nclients ; i + + ) {
if ( server - > clients [ i ] - > watch = = watch ) {
client = server - > clients [ i ] ;
2007-06-26 19:11:00 +00:00
break ;
2008-12-04 22:09:35 +00:00
}
2007-06-26 19:11:00 +00:00
}
2007-06-11 12:04:54 +00:00
2008-12-04 22:16:40 +00:00
if ( ! client ) {
pthread_mutex_unlock ( & server - > lock ) ;
2007-06-26 19:11:00 +00:00
return ;
2008-12-04 22:16:40 +00:00
}
pthread_mutex_lock ( & client - > lock ) ;
pthread_mutex_unlock ( & server - > lock ) ;
2007-06-11 12:04:54 +00:00
2008-11-19 16:19:36 +00:00
if ( client - > fd ! = fd )
return ;
2008-10-23 13:18:18 +00:00
if ( events = = VIR_EVENT_HANDLE_WRITABLE )
2007-06-26 19:11:00 +00:00
qemudDispatchClientWrite ( server , client ) ;
2008-10-23 13:18:18 +00:00
else if ( events = = VIR_EVENT_HANDLE_READABLE )
2007-06-26 19:11:00 +00:00
qemudDispatchClientRead ( server , client ) ;
else
qemudDispatchClientFailure ( server , client ) ;
2008-12-04 22:16:40 +00:00
pthread_mutex_unlock ( & client - > lock ) ;
2007-06-26 19:11:00 +00:00
}
static int qemudRegisterClientEvent ( struct qemud_server * server ,
struct qemud_client * client ,
2008-12-04 22:16:40 +00:00
int update ) {
2007-12-05 15:27:08 +00:00
int mode ;
switch ( client - > mode ) {
case QEMUD_MODE_TLS_HANDSHAKE :
if ( gnutls_record_get_direction ( client - > tlssession ) = = 0 )
2008-10-23 13:18:18 +00:00
mode = VIR_EVENT_HANDLE_READABLE ;
2007-12-05 15:27:08 +00:00
else
2008-10-23 13:18:18 +00:00
mode = VIR_EVENT_HANDLE_WRITABLE ;
2007-12-05 15:27:08 +00:00
break ;
case QEMUD_MODE_RX_HEADER :
case QEMUD_MODE_RX_PAYLOAD :
2008-10-23 13:18:18 +00:00
mode = VIR_EVENT_HANDLE_READABLE ;
2007-12-05 15:27:08 +00:00
break ;
case QEMUD_MODE_TX_PACKET :
2008-10-23 13:18:18 +00:00
mode = VIR_EVENT_HANDLE_WRITABLE ;
2007-12-05 15:27:08 +00:00
break ;
2008-12-04 22:16:40 +00:00
case QEMUD_MODE_WAIT_DISPATCH :
mode = 0 ;
break ;
2007-12-05 15:27:08 +00:00
default :
return - 1 ;
}
2008-12-04 22:16:40 +00:00
if ( update ) {
virEventUpdateHandleImpl ( client - > watch , mode ) ;
} else {
if ( ( client - > watch = virEventAddHandleImpl ( client - > fd ,
mode ,
qemudDispatchClientEvent ,
server , NULL ) ) < 0 )
2007-06-26 19:11:00 +00:00
return - 1 ;
2008-12-04 22:16:40 +00:00
}
2007-06-26 19:11:00 +00:00
return 0 ;
}
2008-10-23 13:18:18 +00:00
static void
2008-11-19 16:19:36 +00:00
qemudDispatchServerEvent ( int watch , int fd , int events , void * opaque ) {
2007-06-26 19:11:00 +00:00
struct qemud_server * server = ( struct qemud_server * ) opaque ;
2008-12-04 22:16:40 +00:00
struct qemud_socket * sock ;
pthread_mutex_lock ( & server - > lock ) ;
sock = server - > sockets ;
2007-06-26 19:11:00 +00:00
2007-03-05 17:15:20 +00:00
while ( sock ) {
2008-11-19 16:19:36 +00:00
if ( sock - > watch = = watch )
2007-06-26 19:11:00 +00:00
break ;
sock = sock - > next ;
2007-03-05 17:15:20 +00:00
}
2007-02-14 01:40:09 +00:00
2008-12-04 22:16:40 +00:00
if ( sock & & sock - > fd = = fd & & events )
2007-06-26 19:11:00 +00:00
qemudDispatchServer ( server , sock ) ;
2008-12-04 22:16:40 +00:00
pthread_mutex_unlock ( & server - > lock ) ;
2007-06-26 19:11:00 +00:00
}
2007-06-26 20:51:00 +00:00
static int qemudOneLoop ( void ) {
2007-03-27 10:28:45 +00:00
sig_atomic_t errors ;
2007-02-14 01:40:09 +00:00
2007-06-26 19:11:00 +00:00
if ( virEventRunOnce ( ) < 0 )
2007-02-14 01:40:09 +00:00
return - 1 ;
2007-03-27 10:28:45 +00:00
/* Check for any signal handling errors and log them. */
errors = sig_errors ;
if ( errors ) {
sig_errors - = errors ;
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " Signal handler reported %d errors: last error: %s " ) ,
2007-03-27 10:28:45 +00:00
errors , strerror ( sig_lasterrno ) ) ;
return - 1 ;
}
2007-02-14 01:40:09 +00:00
return 0 ;
}
2007-06-26 22:56:14 +00:00
static void qemudInactiveTimer ( int timer ATTRIBUTE_UNUSED , void * data ) {
struct qemud_server * server = ( struct qemud_server * ) data ;
2008-12-22 12:53:26 +00:00
DEBUG0 ( " Got inactive timer expiry " ) ;
2007-06-26 22:56:14 +00:00
if ( ! virStateActive ( ) ) {
2008-12-22 12:53:26 +00:00
DEBUG0 ( " No state active, shutting down " ) ;
2007-06-26 22:56:14 +00:00
server - > shutdown = 1 ;
}
}
2007-06-11 12:04:54 +00:00
static int qemudRunLoop ( struct qemud_server * server ) {
2007-06-26 22:56:14 +00:00
int timerid = - 1 ;
2008-12-04 22:16:40 +00:00
int ret = - 1 , i ;
pthread_mutex_lock ( & server - > lock ) ;
2008-12-04 22:18:44 +00:00
server - > nworkers = min_workers ;
2008-12-04 22:16:40 +00:00
if ( VIR_ALLOC_N ( server - > workers , server - > nworkers ) < 0 ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR0 ( _ ( " Failed to allocate workers " ) ) ;
2008-12-04 22:16:40 +00:00
return - 1 ;
}
for ( i = 0 ; i < server - > nworkers ; i + + ) {
pthread_attr_t attr ;
pthread_attr_init ( & attr ) ;
pthread_attr_setdetachstate ( & attr , 1 ) ;
pthread_create ( & server - > workers [ i ] ,
& attr ,
qemudWorker ,
server ) ;
}
2007-06-26 22:56:14 +00:00
for ( ; ; ) {
/* A shutdown timeout is specified, so check
* if any drivers have active state , if not
* shutdown after timeout seconds
*/
if ( timeout > 0 & & ! virStateActive ( ) & & ! server - > clients ) {
2008-11-19 16:24:01 +00:00
timerid = virEventAddTimeoutImpl ( timeout * 1000 ,
qemudInactiveTimer ,
server , NULL ) ;
2008-12-22 12:53:26 +00:00
DEBUG ( " Scheduling shutdown timer %d " , timerid ) ;
2007-06-26 22:56:14 +00:00
}
2008-12-04 22:16:40 +00:00
pthread_mutex_unlock ( & server - > lock ) ;
2007-06-26 22:56:14 +00:00
if ( qemudOneLoop ( ) < 0 )
break ;
2008-12-04 22:16:40 +00:00
pthread_mutex_lock ( & server - > lock ) ;
reprocess :
for ( i = 0 ; i < server - > nclients ; i + + ) {
int inactive ;
pthread_mutex_lock ( & server - > clients [ i ] - > lock ) ;
inactive = server - > clients [ i ] - > fd = = - 1
& & server - > clients [ i ] - > refs = = 0 ;
pthread_mutex_unlock ( & server - > clients [ i ] - > lock ) ;
if ( inactive ) {
if ( server - > clients [ i ] - > conn )
virConnectClose ( server - > clients [ i ] - > conn ) ;
VIR_FREE ( server - > clients [ i ] ) ;
server - > nclients - - ;
if ( i < server - > nclients ) {
memmove ( server - > clients + i ,
server - > clients + i + 1 ,
server - > nclients - i ) ;
goto reprocess ;
}
}
}
2007-02-14 01:40:09 +00:00
2007-06-26 22:56:14 +00:00
/* Unregister any timeout that's active, since we
* just had an event processed
*/
if ( timerid ! = - 1 ) {
2008-12-22 12:53:26 +00:00
DEBUG ( " Removing shutdown timer %d " , timerid ) ;
2007-06-26 22:56:14 +00:00
virEventRemoveTimeoutImpl ( timerid ) ;
timerid = - 1 ;
}
2007-02-14 01:40:09 +00:00
2008-12-04 22:16:40 +00:00
if ( server - > shutdown ) {
ret = 0 ;
break ;
}
2007-06-26 22:56:14 +00:00
}
2008-12-04 22:16:40 +00:00
for ( i = 0 ; i < server - > nworkers ; i + + ) {
pthread_t thread = server - > workers [ i ] ;
pthread_mutex_unlock ( & server - > lock ) ;
pthread_join ( thread , NULL ) ;
pthread_mutex_lock ( & server - > lock ) ;
}
2008-12-12 12:19:21 +00:00
free ( server - > workers ) ;
2008-12-04 22:16:40 +00:00
pthread_mutex_unlock ( & server - > lock ) ;
return ret ;
2007-02-14 01:40:09 +00:00
}
static void qemudCleanup ( struct qemud_server * server ) {
2007-02-20 17:51:41 +00:00
struct qemud_socket * sock ;
2007-02-16 18:28:17 +00:00
close ( server - > sigread ) ;
2007-02-20 17:51:41 +00:00
sock = server - > sockets ;
2007-02-14 01:40:09 +00:00
while ( sock ) {
2007-02-20 17:51:41 +00:00
struct qemud_socket * next = sock - > next ;
2007-02-14 01:40:09 +00:00
close ( sock - > fd ) ;
2007-02-20 17:51:41 +00:00
free ( sock ) ;
sock = next ;
2007-02-14 01:40:09 +00:00
}
2007-02-20 17:51:41 +00:00
2007-12-05 19:25:44 +00:00
# ifdef HAVE_SASL
2007-12-05 15:34:05 +00:00
if ( server - > saslUsernameWhitelist ) {
char * * list = server - > saslUsernameWhitelist ;
while ( * list ) {
2008-01-29 17:41:07 +00:00
free ( * list ) ;
2007-12-05 15:34:05 +00:00
list + + ;
}
2008-03-03 13:17:05 +00:00
free ( server - > saslUsernameWhitelist ) ;
2007-12-05 15:34:05 +00:00
}
2007-12-05 19:25:44 +00:00
# endif
2007-02-20 17:51:41 +00:00
2007-06-26 22:56:14 +00:00
virStateCleanup ( ) ;
2007-06-11 12:04:54 +00:00
2007-02-14 01:40:09 +00:00
free ( server ) ;
}
Detect heap allocation failure; factor out some duplication.
* qemud/qemud.c (tls_port, tcp_port, mdns_name, tls_allowed_ip_list):
(tls_allowed_dn_list): Remove "const", now that we free these.
(unix_sock_rw_mask): Rename from unix_sock_rw_perms, so that
the latter name can be used as a local string variable, so that the
variable name matches the config attribute name.
(unix_sock_ro_mask): Rename from unix_sock_ro_perms, likewise.
(remoteCheckDN, remoteCheckAccess): Adapt to const removal.
(qemudDispatchServer): Check for heap allocation failure.
(remoteConfigGetStringList): New function, based on code from Dan Berrangé.
(CHECK_TYPE): Remove macro.
(checkType): New function.
(GET_CONF_INT, GET_CONF_STR): New macros.
(remoteReadConfigFile): Use new macros to avoid duplication and to
check for allocation failure.
* src/conf.h (virConfTypeName): New static inline function.
2007-11-30 15:43:42 +00:00
/* Allocate an array of malloc'd strings from the config file, filename
* ( used only in diagnostics ) , using handle " conf " . Upon error , return - 1
* and free any allocated memory . Otherwise , save the array in * list_arg
* and return 0.
*/
static int
remoteConfigGetStringList ( virConfPtr conf , const char * key , char * * * list_arg ,
const char * filename )
{
char * * list ;
virConfValuePtr p = virConfGetValue ( conf , key ) ;
if ( ! p )
return 0 ;
switch ( p - > type ) {
case VIR_CONF_STRING :
2008-06-06 10:52:01 +00:00
if ( VIR_ALLOC_N ( list , 2 ) < 0 ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " failed to allocate memory for %s config list " ) , key ) ;
Detect heap allocation failure; factor out some duplication.
* qemud/qemud.c (tls_port, tcp_port, mdns_name, tls_allowed_ip_list):
(tls_allowed_dn_list): Remove "const", now that we free these.
(unix_sock_rw_mask): Rename from unix_sock_rw_perms, so that
the latter name can be used as a local string variable, so that the
variable name matches the config attribute name.
(unix_sock_ro_mask): Rename from unix_sock_ro_perms, likewise.
(remoteCheckDN, remoteCheckAccess): Adapt to const removal.
(qemudDispatchServer): Check for heap allocation failure.
(remoteConfigGetStringList): New function, based on code from Dan Berrangé.
(CHECK_TYPE): Remove macro.
(checkType): New function.
(GET_CONF_INT, GET_CONF_STR): New macros.
(remoteReadConfigFile): Use new macros to avoid duplication and to
check for allocation failure.
* src/conf.h (virConfTypeName): New static inline function.
2007-11-30 15:43:42 +00:00
return - 1 ;
}
list [ 0 ] = strdup ( p - > str ) ;
list [ 1 ] = NULL ;
if ( list [ 0 ] = = NULL ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " failed to allocate memory for %s config list value " ) ,
Detect heap allocation failure; factor out some duplication.
* qemud/qemud.c (tls_port, tcp_port, mdns_name, tls_allowed_ip_list):
(tls_allowed_dn_list): Remove "const", now that we free these.
(unix_sock_rw_mask): Rename from unix_sock_rw_perms, so that
the latter name can be used as a local string variable, so that the
variable name matches the config attribute name.
(unix_sock_ro_mask): Rename from unix_sock_ro_perms, likewise.
(remoteCheckDN, remoteCheckAccess): Adapt to const removal.
(qemudDispatchServer): Check for heap allocation failure.
(remoteConfigGetStringList): New function, based on code from Dan Berrangé.
(CHECK_TYPE): Remove macro.
(checkType): New function.
(GET_CONF_INT, GET_CONF_STR): New macros.
(remoteReadConfigFile): Use new macros to avoid duplication and to
check for allocation failure.
* src/conf.h (virConfTypeName): New static inline function.
2007-11-30 15:43:42 +00:00
key ) ;
2008-06-06 10:52:01 +00:00
VIR_FREE ( list ) ;
Detect heap allocation failure; factor out some duplication.
* qemud/qemud.c (tls_port, tcp_port, mdns_name, tls_allowed_ip_list):
(tls_allowed_dn_list): Remove "const", now that we free these.
(unix_sock_rw_mask): Rename from unix_sock_rw_perms, so that
the latter name can be used as a local string variable, so that the
variable name matches the config attribute name.
(unix_sock_ro_mask): Rename from unix_sock_ro_perms, likewise.
(remoteCheckDN, remoteCheckAccess): Adapt to const removal.
(qemudDispatchServer): Check for heap allocation failure.
(remoteConfigGetStringList): New function, based on code from Dan Berrangé.
(CHECK_TYPE): Remove macro.
(checkType): New function.
(GET_CONF_INT, GET_CONF_STR): New macros.
(remoteReadConfigFile): Use new macros to avoid duplication and to
check for allocation failure.
* src/conf.h (virConfTypeName): New static inline function.
2007-11-30 15:43:42 +00:00
return - 1 ;
}
break ;
case VIR_CONF_LIST : {
int i , len = 0 ;
virConfValuePtr pp ;
for ( pp = p - > list ; pp ; pp = pp - > next )
len + + ;
2008-06-06 10:52:01 +00:00
if ( VIR_ALLOC_N ( list , 1 + len ) < 0 ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " failed to allocate memory for %s config list " ) , key ) ;
Detect heap allocation failure; factor out some duplication.
* qemud/qemud.c (tls_port, tcp_port, mdns_name, tls_allowed_ip_list):
(tls_allowed_dn_list): Remove "const", now that we free these.
(unix_sock_rw_mask): Rename from unix_sock_rw_perms, so that
the latter name can be used as a local string variable, so that the
variable name matches the config attribute name.
(unix_sock_ro_mask): Rename from unix_sock_ro_perms, likewise.
(remoteCheckDN, remoteCheckAccess): Adapt to const removal.
(qemudDispatchServer): Check for heap allocation failure.
(remoteConfigGetStringList): New function, based on code from Dan Berrangé.
(CHECK_TYPE): Remove macro.
(checkType): New function.
(GET_CONF_INT, GET_CONF_STR): New macros.
(remoteReadConfigFile): Use new macros to avoid duplication and to
check for allocation failure.
* src/conf.h (virConfTypeName): New static inline function.
2007-11-30 15:43:42 +00:00
return - 1 ;
}
for ( i = 0 , pp = p - > list ; pp ; + + i , pp = pp - > next ) {
if ( pp - > type ! = VIR_CONF_STRING ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " remoteReadConfigFile: %s: %s: "
" must be a string or list of strings \n " ) ,
Detect heap allocation failure; factor out some duplication.
* qemud/qemud.c (tls_port, tcp_port, mdns_name, tls_allowed_ip_list):
(tls_allowed_dn_list): Remove "const", now that we free these.
(unix_sock_rw_mask): Rename from unix_sock_rw_perms, so that
the latter name can be used as a local string variable, so that the
variable name matches the config attribute name.
(unix_sock_ro_mask): Rename from unix_sock_ro_perms, likewise.
(remoteCheckDN, remoteCheckAccess): Adapt to const removal.
(qemudDispatchServer): Check for heap allocation failure.
(remoteConfigGetStringList): New function, based on code from Dan Berrangé.
(CHECK_TYPE): Remove macro.
(checkType): New function.
(GET_CONF_INT, GET_CONF_STR): New macros.
(remoteReadConfigFile): Use new macros to avoid duplication and to
check for allocation failure.
* src/conf.h (virConfTypeName): New static inline function.
2007-11-30 15:43:42 +00:00
filename , key ) ;
2008-06-06 10:52:01 +00:00
VIR_FREE ( list ) ;
Detect heap allocation failure; factor out some duplication.
* qemud/qemud.c (tls_port, tcp_port, mdns_name, tls_allowed_ip_list):
(tls_allowed_dn_list): Remove "const", now that we free these.
(unix_sock_rw_mask): Rename from unix_sock_rw_perms, so that
the latter name can be used as a local string variable, so that the
variable name matches the config attribute name.
(unix_sock_ro_mask): Rename from unix_sock_ro_perms, likewise.
(remoteCheckDN, remoteCheckAccess): Adapt to const removal.
(qemudDispatchServer): Check for heap allocation failure.
(remoteConfigGetStringList): New function, based on code from Dan Berrangé.
(CHECK_TYPE): Remove macro.
(checkType): New function.
(GET_CONF_INT, GET_CONF_STR): New macros.
(remoteReadConfigFile): Use new macros to avoid duplication and to
check for allocation failure.
* src/conf.h (virConfTypeName): New static inline function.
2007-11-30 15:43:42 +00:00
return - 1 ;
}
list [ i ] = strdup ( pp - > str ) ;
if ( list [ i ] = = NULL ) {
int j ;
for ( j = 0 ; j < i ; j + + )
2008-06-06 10:52:01 +00:00
VIR_FREE ( list [ j ] ) ;
VIR_FREE ( list ) ;
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " failed to allocate memory for %s config list value " ) ,
key ) ;
Detect heap allocation failure; factor out some duplication.
* qemud/qemud.c (tls_port, tcp_port, mdns_name, tls_allowed_ip_list):
(tls_allowed_dn_list): Remove "const", now that we free these.
(unix_sock_rw_mask): Rename from unix_sock_rw_perms, so that
the latter name can be used as a local string variable, so that the
variable name matches the config attribute name.
(unix_sock_ro_mask): Rename from unix_sock_ro_perms, likewise.
(remoteCheckDN, remoteCheckAccess): Adapt to const removal.
(qemudDispatchServer): Check for heap allocation failure.
(remoteConfigGetStringList): New function, based on code from Dan Berrangé.
(CHECK_TYPE): Remove macro.
(checkType): New function.
(GET_CONF_INT, GET_CONF_STR): New macros.
(remoteReadConfigFile): Use new macros to avoid duplication and to
check for allocation failure.
* src/conf.h (virConfTypeName): New static inline function.
2007-11-30 15:43:42 +00:00
return - 1 ;
}
}
list [ i ] = NULL ;
break ;
}
default :
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " remoteReadConfigFile: %s: %s: "
" must be a string or list of strings \n " ) ,
Detect heap allocation failure; factor out some duplication.
* qemud/qemud.c (tls_port, tcp_port, mdns_name, tls_allowed_ip_list):
(tls_allowed_dn_list): Remove "const", now that we free these.
(unix_sock_rw_mask): Rename from unix_sock_rw_perms, so that
the latter name can be used as a local string variable, so that the
variable name matches the config attribute name.
(unix_sock_ro_mask): Rename from unix_sock_ro_perms, likewise.
(remoteCheckDN, remoteCheckAccess): Adapt to const removal.
(qemudDispatchServer): Check for heap allocation failure.
(remoteConfigGetStringList): New function, based on code from Dan Berrangé.
(CHECK_TYPE): Remove macro.
(checkType): New function.
(GET_CONF_INT, GET_CONF_STR): New macros.
(remoteReadConfigFile): Use new macros to avoid duplication and to
check for allocation failure.
* src/conf.h (virConfTypeName): New static inline function.
2007-11-30 15:43:42 +00:00
filename , key ) ;
return - 1 ;
}
* list_arg = list ;
return 0 ;
}
/* A helper function used by each of the following macros. */
static int
checkType ( virConfValuePtr p , const char * filename ,
const char * key , virConfType required_type )
{
if ( p - > type ! = required_type ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " remoteReadConfigFile: %s: %s: invalid type: "
Mark all qemudLog diagnostics for translation.
* po/POTFILES.in: Add names of many new files.
* Makefile.maint (err_func_re): Add qemudLog.
Mark diagnostics with _(...). Split some long lines.
* qemud/qemud.c (remoteCheckCertFile, remoteInitializeGnuTLS):
(qemudDispatchSignalEvent, qemudSetCloseExec, qemudSetNonBlock):
(qemudWritePidFile, qemudListenUnix, remoteMakeSockets):
(remoteListenTCP, qemudInitPaths, qemudInitialize):
(qemudNetworkInit, remoteInitializeTLSSession, remoteCheckDN):
(remoteCheckCertificate, remoteCheckAccess, qemudDispatchServer):
(qemudClientReadBuf, qemudDispatchClientRead):
(qemudClientWriteBuf, qemudDispatchClientWrite, qemudOneLoop):
(remoteConfigGetStringList, checkType, GET_CONF_STR):
(remoteConfigGetAuth, remoteReadConfigFile, main):
* qemud/remote.c (remoteDispatchAuthSaslInit, remoteSASLCheckSSF):
(remoteSASLCheckAccess, remoteDispatchAuthSaslStart):
(remoteDispatchAuthSaslStep, remoteDispatchAuthSaslInit):
(remoteDispatchAuthSaslStart, remoteDispatchAuthSaslStep):
(qemudGetSocketIdentity, remoteDispatchAuthPolkit):
* src/iptables.c (notifyRulesUpdated, MAX_FILE_LEN, iptRulesSave):
(iptRulesReload):
* src/qemu_conf.c (qemudExtractVersionInfo, qemudLoadConfig):
(qemudLoadNetworkConfig, qemudScanConfigDir):
* src/qemu_driver.c (qemudSetCloseExec, qemudSetNonBlock):
(qemudAutostartConfigs, qemudStartup, qemudReload):
(qemudWaitForMonitor, qemudStartVMDaemon, qemudVMData):
(qemudShutdownVMDaemon, qemudStartNetworkDaemon):
(qemudShutdownNetworkDaemon, qemudMonitorCommand):
(qemudDomainUndefine, qemudNetworkUndefine):
* src/uuid.c (virUUIDGenerate):
* src/xm_internal.c (xenXMAttachInterface):
2008-02-07 16:50:17 +00:00
" got %s; expected %s \n " ) , filename , key ,
Detect heap allocation failure; factor out some duplication.
* qemud/qemud.c (tls_port, tcp_port, mdns_name, tls_allowed_ip_list):
(tls_allowed_dn_list): Remove "const", now that we free these.
(unix_sock_rw_mask): Rename from unix_sock_rw_perms, so that
the latter name can be used as a local string variable, so that the
variable name matches the config attribute name.
(unix_sock_ro_mask): Rename from unix_sock_ro_perms, likewise.
(remoteCheckDN, remoteCheckAccess): Adapt to const removal.
(qemudDispatchServer): Check for heap allocation failure.
(remoteConfigGetStringList): New function, based on code from Dan Berrangé.
(CHECK_TYPE): Remove macro.
(checkType): New function.
(GET_CONF_INT, GET_CONF_STR): New macros.
(remoteReadConfigFile): Use new macros to avoid duplication and to
check for allocation failure.
* src/conf.h (virConfTypeName): New static inline function.
2007-11-30 15:43:42 +00:00
virConfTypeName ( p - > type ) ,
virConfTypeName ( required_type ) ) ;
return - 1 ;
}
return 0 ;
}
/* If there is no config data for the key, #var_name, then do nothing.
If there is valid data of type VIR_CONF_STRING , and strdup succeeds ,
store the result in var_name . Otherwise , ( i . e . invalid type , or strdup
failure ) , give a diagnostic and " goto " the cleanup - and - fail label . */
# define GET_CONF_STR(conf, filename, var_name) \
do { \
virConfValuePtr p = virConfGetValue ( conf , # var_name ) ; \
if ( p ) { \
if ( checkType ( p , filename , # var_name , VIR_CONF_STRING ) < 0 ) \
goto free_and_fail ; \
( var_name ) = strdup ( p - > str ) ; \
if ( ( var_name ) = = NULL ) { \
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " remoteReadConfigFile: %s \n " ) , strerror ( errno ) ) ; \
Detect heap allocation failure; factor out some duplication.
* qemud/qemud.c (tls_port, tcp_port, mdns_name, tls_allowed_ip_list):
(tls_allowed_dn_list): Remove "const", now that we free these.
(unix_sock_rw_mask): Rename from unix_sock_rw_perms, so that
the latter name can be used as a local string variable, so that the
variable name matches the config attribute name.
(unix_sock_ro_mask): Rename from unix_sock_ro_perms, likewise.
(remoteCheckDN, remoteCheckAccess): Adapt to const removal.
(qemudDispatchServer): Check for heap allocation failure.
(remoteConfigGetStringList): New function, based on code from Dan Berrangé.
(CHECK_TYPE): Remove macro.
(checkType): New function.
(GET_CONF_INT, GET_CONF_STR): New macros.
(remoteReadConfigFile): Use new macros to avoid duplication and to
check for allocation failure.
* src/conf.h (virConfTypeName): New static inline function.
2007-11-30 15:43:42 +00:00
goto free_and_fail ; \
} \
} \
} while ( 0 )
/* Like GET_CONF_STR, but for integral values. */
# define GET_CONF_INT(conf, filename, var_name) \
do { \
virConfValuePtr p = virConfGetValue ( conf , # var_name ) ; \
if ( p ) { \
if ( checkType ( p , filename , # var_name , VIR_CONF_LONG ) < 0 ) \
goto free_and_fail ; \
( var_name ) = p - > l ; \
} \
} while ( 0 )
2007-12-05 15:34:05 +00:00
static int remoteConfigGetAuth ( virConfPtr conf , const char * key , int * auth , const char * filename ) {
virConfValuePtr p ;
p = virConfGetValue ( conf , key ) ;
if ( ! p )
return 0 ;
2007-12-11 21:20:13 +00:00
if ( checkType ( p , filename , key , VIR_CONF_STRING ) < 0 )
2007-12-05 15:34:05 +00:00
return - 1 ;
if ( ! p - > str )
return 0 ;
if ( STREQ ( p - > str , " none " ) ) {
* auth = REMOTE_AUTH_NONE ;
# if HAVE_SASL
} else if ( STREQ ( p - > str , " sasl " ) ) {
* auth = REMOTE_AUTH_SASL ;
2007-12-05 18:21:27 +00:00
# endif
# if HAVE_POLKIT
} else if ( STREQ ( p - > str , " polkit " ) ) {
* auth = REMOTE_AUTH_POLKIT ;
2007-12-05 15:34:05 +00:00
# endif
} else {
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " remoteReadConfigFile: %s: %s: unsupported auth %s \n " ) ,
Mark all qemudLog diagnostics for translation.
* po/POTFILES.in: Add names of many new files.
* Makefile.maint (err_func_re): Add qemudLog.
Mark diagnostics with _(...). Split some long lines.
* qemud/qemud.c (remoteCheckCertFile, remoteInitializeGnuTLS):
(qemudDispatchSignalEvent, qemudSetCloseExec, qemudSetNonBlock):
(qemudWritePidFile, qemudListenUnix, remoteMakeSockets):
(remoteListenTCP, qemudInitPaths, qemudInitialize):
(qemudNetworkInit, remoteInitializeTLSSession, remoteCheckDN):
(remoteCheckCertificate, remoteCheckAccess, qemudDispatchServer):
(qemudClientReadBuf, qemudDispatchClientRead):
(qemudClientWriteBuf, qemudDispatchClientWrite, qemudOneLoop):
(remoteConfigGetStringList, checkType, GET_CONF_STR):
(remoteConfigGetAuth, remoteReadConfigFile, main):
* qemud/remote.c (remoteDispatchAuthSaslInit, remoteSASLCheckSSF):
(remoteSASLCheckAccess, remoteDispatchAuthSaslStart):
(remoteDispatchAuthSaslStep, remoteDispatchAuthSaslInit):
(remoteDispatchAuthSaslStart, remoteDispatchAuthSaslStep):
(qemudGetSocketIdentity, remoteDispatchAuthPolkit):
* src/iptables.c (notifyRulesUpdated, MAX_FILE_LEN, iptRulesSave):
(iptRulesReload):
* src/qemu_conf.c (qemudExtractVersionInfo, qemudLoadConfig):
(qemudLoadNetworkConfig, qemudScanConfigDir):
* src/qemu_driver.c (qemudSetCloseExec, qemudSetNonBlock):
(qemudAutostartConfigs, qemudStartup, qemudReload):
(qemudWaitForMonitor, qemudStartVMDaemon, qemudVMData):
(qemudShutdownVMDaemon, qemudStartNetworkDaemon):
(qemudShutdownNetworkDaemon, qemudMonitorCommand):
(qemudDomainUndefine, qemudNetworkUndefine):
* src/uuid.c (virUUIDGenerate):
* src/xm_internal.c (xenXMAttachInterface):
2008-02-07 16:50:17 +00:00
filename , key , p - > str ) ;
2007-12-05 15:34:05 +00:00
return - 1 ;
}
return 0 ;
}
2007-12-05 19:25:44 +00:00
# ifdef HAVE_SASL
static inline int
remoteReadSaslAllowedUsernameList ( virConfPtr conf ,
struct qemud_server * server ,
const char * filename )
{
return
remoteConfigGetStringList ( conf , " sasl_allowed_username_list " ,
& server - > saslUsernameWhitelist , filename ) ;
}
# else
static inline int
remoteReadSaslAllowedUsernameList ( virConfPtr conf ATTRIBUTE_UNUSED ,
struct qemud_server * server ATTRIBUTE_UNUSED ,
const char * filename ATTRIBUTE_UNUSED )
{
return 0 ;
}
# endif
2008-12-22 12:53:26 +00:00
/*
* Set up the logging environment
* By default if daemonized all errors go to syslog and the logging
* is also saved onto the logfile libvird . log , but if verbose or error
* debugging is asked for then output informations or debug .
*/
2008-12-22 16:16:10 +00:00
static int
2008-12-22 12:53:26 +00:00
qemudSetLogging ( virConfPtr conf , const char * filename ) {
2008-12-22 16:16:10 +00:00
char * debugEnv ;
int ret = - 1 ;
2008-12-22 12:53:26 +00:00
virLogReset ( ) ;
2008-12-22 16:16:10 +00:00
/*
* look for default logging level first from config file ,
* then from environment variable and finally from command
* line options
*/
2008-12-22 12:53:26 +00:00
GET_CONF_INT ( conf , filename , log_level ) ;
2008-12-22 16:16:10 +00:00
debugEnv = getenv ( " LIBVIRT_DEBUG " ) ;
if ( debugEnv & & * debugEnv & & * debugEnv ! = ' 0 ' ) {
if ( STREQ ( debugEnv , " 2 " ) | | STREQ ( debugEnv , " info " ) )
log_level = VIR_LOG_INFO ;
else if ( STREQ ( debugEnv , " 3 " ) | | STREQ ( debugEnv , " warning " ) )
log_level = VIR_LOG_WARN ;
else if ( STREQ ( debugEnv , " 4 " ) | | STREQ ( debugEnv , " error " ) )
log_level = VIR_LOG_ERROR ;
else
log_level = VIR_LOG_DEBUG ;
}
2008-12-22 12:53:26 +00:00
if ( ( verbose ) & & ( log_level > = VIR_LOG_WARN ) )
log_level = VIR_LOG_INFO ;
virLogSetDefaultPriority ( log_level ) ;
/* there is no default filters */
GET_CONF_STR ( conf , filename , log_filters ) ;
virLogParseFilters ( log_filters ) ;
/*
* by default save all warning and errors to syslog or
* all logs to stderr if not running as daemon
*/
GET_CONF_STR ( conf , filename , log_outputs ) ;
if ( log_outputs = = NULL ) {
if ( godaemon )
virLogParseOutputs ( " 3:syslog:libvirtd " ) ;
else
virLogParseOutputs ( " 0:stderr:libvirtd " ) ;
} else
virLogParseOutputs ( log_outputs ) ;
2008-12-22 16:16:10 +00:00
ret = 0 ;
2008-12-22 12:53:26 +00:00
free_and_fail :
VIR_FREE ( log_filters ) ;
VIR_FREE ( log_outputs ) ;
2008-12-22 16:16:10 +00:00
return ( ret ) ;
2008-12-22 12:53:26 +00:00
}
2007-12-05 19:25:44 +00:00
2007-06-11 12:04:54 +00:00
/* Read the config file if it exists.
* Only used in the remote case , hence the name .
*/
static int
2007-12-05 15:34:05 +00:00
remoteReadConfigFile ( struct qemud_server * server , const char * filename )
2007-06-11 12:04:54 +00:00
{
virConfPtr conf ;
Detect heap allocation failure; factor out some duplication.
* qemud/qemud.c (tls_port, tcp_port, mdns_name, tls_allowed_ip_list):
(tls_allowed_dn_list): Remove "const", now that we free these.
(unix_sock_rw_mask): Rename from unix_sock_rw_perms, so that
the latter name can be used as a local string variable, so that the
variable name matches the config attribute name.
(unix_sock_ro_mask): Rename from unix_sock_ro_perms, likewise.
(remoteCheckDN, remoteCheckAccess): Adapt to const removal.
(qemudDispatchServer): Check for heap allocation failure.
(remoteConfigGetStringList): New function, based on code from Dan Berrangé.
(CHECK_TYPE): Remove macro.
(checkType): New function.
(GET_CONF_INT, GET_CONF_STR): New macros.
(remoteReadConfigFile): Use new macros to avoid duplication and to
check for allocation failure.
* src/conf.h (virConfTypeName): New static inline function.
2007-11-30 15:43:42 +00:00
/* The following variable names must match the corresponding
configuration strings . */
char * unix_sock_ro_perms = NULL ;
char * unix_sock_rw_perms = NULL ;
char * unix_sock_group = NULL ;
2008-07-30 08:47:10 +00:00
# if HAVE_POLKIT
/* Change the default back to no auth for non-root */
if ( getuid ( ) ! = 0 & & auth_unix_rw = = REMOTE_AUTH_POLKIT )
auth_unix_rw = REMOTE_AUTH_NONE ;
if ( getuid ( ) ! = 0 & & auth_unix_ro = = REMOTE_AUTH_POLKIT )
auth_unix_ro = REMOTE_AUTH_NONE ;
# endif
2007-06-11 12:04:54 +00:00
conf = virConfReadFile ( filename ) ;
2009-01-12 18:22:32 +00:00
if ( ! conf ) return - 1 ;
2007-06-11 12:04:54 +00:00
2008-12-22 12:53:26 +00:00
/*
* First get all the logging settings and activate them
*/
2008-12-22 16:16:10 +00:00
if ( qemudSetLogging ( conf , filename ) < 0 )
goto free_and_fail ;
2008-12-22 12:53:26 +00:00
2007-12-05 18:56:27 +00:00
GET_CONF_INT ( conf , filename , listen_tcp ) ;
GET_CONF_INT ( conf , filename , listen_tls ) ;
Detect heap allocation failure; factor out some duplication.
* qemud/qemud.c (tls_port, tcp_port, mdns_name, tls_allowed_ip_list):
(tls_allowed_dn_list): Remove "const", now that we free these.
(unix_sock_rw_mask): Rename from unix_sock_rw_perms, so that
the latter name can be used as a local string variable, so that the
variable name matches the config attribute name.
(unix_sock_ro_mask): Rename from unix_sock_ro_perms, likewise.
(remoteCheckDN, remoteCheckAccess): Adapt to const removal.
(qemudDispatchServer): Check for heap allocation failure.
(remoteConfigGetStringList): New function, based on code from Dan Berrangé.
(CHECK_TYPE): Remove macro.
(checkType): New function.
(GET_CONF_INT, GET_CONF_STR): New macros.
(remoteReadConfigFile): Use new macros to avoid duplication and to
check for allocation failure.
* src/conf.h (virConfTypeName): New static inline function.
2007-11-30 15:43:42 +00:00
GET_CONF_STR ( conf , filename , tls_port ) ;
GET_CONF_STR ( conf , filename , tcp_port ) ;
2008-05-14 20:57:20 +00:00
GET_CONF_STR ( conf , filename , listen_addr ) ;
2008-05-14 21:22:04 +00:00
2007-12-05 15:34:05 +00:00
if ( remoteConfigGetAuth ( conf , " auth_unix_rw " , & auth_unix_rw , filename ) < 0 )
2008-03-03 13:15:57 +00:00
goto free_and_fail ;
2007-12-05 18:21:27 +00:00
# if HAVE_POLKIT
/* Change default perms to be wide-open if PolicyKit is enabled.
* Admin can always override in config file
*/
if ( auth_unix_rw = = REMOTE_AUTH_POLKIT )
unix_sock_rw_mask = 0777 ;
# endif
2007-12-05 15:34:05 +00:00
if ( remoteConfigGetAuth ( conf , " auth_unix_ro " , & auth_unix_ro , filename ) < 0 )
2008-03-03 13:15:57 +00:00
goto free_and_fail ;
2007-12-05 15:34:05 +00:00
if ( remoteConfigGetAuth ( conf , " auth_tcp " , & auth_tcp , filename ) < 0 )
2008-03-03 13:15:57 +00:00
goto free_and_fail ;
2007-12-05 15:34:05 +00:00
if ( remoteConfigGetAuth ( conf , " auth_tls " , & auth_tls , filename ) < 0 )
2008-03-03 13:15:57 +00:00
goto free_and_fail ;
2007-12-05 15:34:05 +00:00
Detect heap allocation failure; factor out some duplication.
* qemud/qemud.c (tls_port, tcp_port, mdns_name, tls_allowed_ip_list):
(tls_allowed_dn_list): Remove "const", now that we free these.
(unix_sock_rw_mask): Rename from unix_sock_rw_perms, so that
the latter name can be used as a local string variable, so that the
variable name matches the config attribute name.
(unix_sock_ro_mask): Rename from unix_sock_ro_perms, likewise.
(remoteCheckDN, remoteCheckAccess): Adapt to const removal.
(qemudDispatchServer): Check for heap allocation failure.
(remoteConfigGetStringList): New function, based on code from Dan Berrangé.
(CHECK_TYPE): Remove macro.
(checkType): New function.
(GET_CONF_INT, GET_CONF_STR): New macros.
(remoteReadConfigFile): Use new macros to avoid duplication and to
check for allocation failure.
* src/conf.h (virConfTypeName): New static inline function.
2007-11-30 15:43:42 +00:00
GET_CONF_STR ( conf , filename , unix_sock_group ) ;
if ( unix_sock_group ) {
2007-09-19 02:28:01 +00:00
if ( getuid ( ) ! = 0 ) {
2009-01-06 18:32:03 +00:00
VIR_WARN0 ( _ ( " Cannot set group when not running as root " ) ) ;
2007-09-19 02:28:01 +00:00
} else {
Detect heap allocation failure; factor out some duplication.
* qemud/qemud.c (tls_port, tcp_port, mdns_name, tls_allowed_ip_list):
(tls_allowed_dn_list): Remove "const", now that we free these.
(unix_sock_rw_mask): Rename from unix_sock_rw_perms, so that
the latter name can be used as a local string variable, so that the
variable name matches the config attribute name.
(unix_sock_ro_mask): Rename from unix_sock_ro_perms, likewise.
(remoteCheckDN, remoteCheckAccess): Adapt to const removal.
(qemudDispatchServer): Check for heap allocation failure.
(remoteConfigGetStringList): New function, based on code from Dan Berrangé.
(CHECK_TYPE): Remove macro.
(checkType): New function.
(GET_CONF_INT, GET_CONF_STR): New macros.
(remoteReadConfigFile): Use new macros to avoid duplication and to
check for allocation failure.
* src/conf.h (virConfTypeName): New static inline function.
2007-11-30 15:43:42 +00:00
struct group * grp = getgrnam ( unix_sock_group ) ;
2007-09-19 02:28:01 +00:00
if ( ! grp ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " Failed to lookup group '%s' " ) , unix_sock_group ) ;
Detect heap allocation failure; factor out some duplication.
* qemud/qemud.c (tls_port, tcp_port, mdns_name, tls_allowed_ip_list):
(tls_allowed_dn_list): Remove "const", now that we free these.
(unix_sock_rw_mask): Rename from unix_sock_rw_perms, so that
the latter name can be used as a local string variable, so that the
variable name matches the config attribute name.
(unix_sock_ro_mask): Rename from unix_sock_ro_perms, likewise.
(remoteCheckDN, remoteCheckAccess): Adapt to const removal.
(qemudDispatchServer): Check for heap allocation failure.
(remoteConfigGetStringList): New function, based on code from Dan Berrangé.
(CHECK_TYPE): Remove macro.
(checkType): New function.
(GET_CONF_INT, GET_CONF_STR): New macros.
(remoteReadConfigFile): Use new macros to avoid duplication and to
check for allocation failure.
* src/conf.h (virConfTypeName): New static inline function.
2007-11-30 15:43:42 +00:00
goto free_and_fail ;
2007-09-19 02:28:01 +00:00
}
unix_sock_gid = grp - > gr_gid ;
}
Detect heap allocation failure; factor out some duplication.
* qemud/qemud.c (tls_port, tcp_port, mdns_name, tls_allowed_ip_list):
(tls_allowed_dn_list): Remove "const", now that we free these.
(unix_sock_rw_mask): Rename from unix_sock_rw_perms, so that
the latter name can be used as a local string variable, so that the
variable name matches the config attribute name.
(unix_sock_ro_mask): Rename from unix_sock_ro_perms, likewise.
(remoteCheckDN, remoteCheckAccess): Adapt to const removal.
(qemudDispatchServer): Check for heap allocation failure.
(remoteConfigGetStringList): New function, based on code from Dan Berrangé.
(CHECK_TYPE): Remove macro.
(checkType): New function.
(GET_CONF_INT, GET_CONF_STR): New macros.
(remoteReadConfigFile): Use new macros to avoid duplication and to
check for allocation failure.
* src/conf.h (virConfTypeName): New static inline function.
2007-11-30 15:43:42 +00:00
free ( unix_sock_group ) ;
unix_sock_group = NULL ;
2007-09-19 02:28:01 +00:00
}
Detect heap allocation failure; factor out some duplication.
* qemud/qemud.c (tls_port, tcp_port, mdns_name, tls_allowed_ip_list):
(tls_allowed_dn_list): Remove "const", now that we free these.
(unix_sock_rw_mask): Rename from unix_sock_rw_perms, so that
the latter name can be used as a local string variable, so that the
variable name matches the config attribute name.
(unix_sock_ro_mask): Rename from unix_sock_ro_perms, likewise.
(remoteCheckDN, remoteCheckAccess): Adapt to const removal.
(qemudDispatchServer): Check for heap allocation failure.
(remoteConfigGetStringList): New function, based on code from Dan Berrangé.
(CHECK_TYPE): Remove macro.
(checkType): New function.
(GET_CONF_INT, GET_CONF_STR): New macros.
(remoteReadConfigFile): Use new macros to avoid duplication and to
check for allocation failure.
* src/conf.h (virConfTypeName): New static inline function.
2007-11-30 15:43:42 +00:00
GET_CONF_STR ( conf , filename , unix_sock_ro_perms ) ;
if ( unix_sock_ro_perms ) {
2008-02-08 09:15:16 +00:00
if ( virStrToLong_i ( unix_sock_ro_perms , NULL , 8 , & unix_sock_ro_mask ) ! = 0 ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " Failed to parse mode '%s' " ) , unix_sock_ro_perms ) ;
Detect heap allocation failure; factor out some duplication.
* qemud/qemud.c (tls_port, tcp_port, mdns_name, tls_allowed_ip_list):
(tls_allowed_dn_list): Remove "const", now that we free these.
(unix_sock_rw_mask): Rename from unix_sock_rw_perms, so that
the latter name can be used as a local string variable, so that the
variable name matches the config attribute name.
(unix_sock_ro_mask): Rename from unix_sock_ro_perms, likewise.
(remoteCheckDN, remoteCheckAccess): Adapt to const removal.
(qemudDispatchServer): Check for heap allocation failure.
(remoteConfigGetStringList): New function, based on code from Dan Berrangé.
(CHECK_TYPE): Remove macro.
(checkType): New function.
(GET_CONF_INT, GET_CONF_STR): New macros.
(remoteReadConfigFile): Use new macros to avoid duplication and to
check for allocation failure.
* src/conf.h (virConfTypeName): New static inline function.
2007-11-30 15:43:42 +00:00
goto free_and_fail ;
2007-09-19 02:28:01 +00:00
}
Detect heap allocation failure; factor out some duplication.
* qemud/qemud.c (tls_port, tcp_port, mdns_name, tls_allowed_ip_list):
(tls_allowed_dn_list): Remove "const", now that we free these.
(unix_sock_rw_mask): Rename from unix_sock_rw_perms, so that
the latter name can be used as a local string variable, so that the
variable name matches the config attribute name.
(unix_sock_ro_mask): Rename from unix_sock_ro_perms, likewise.
(remoteCheckDN, remoteCheckAccess): Adapt to const removal.
(qemudDispatchServer): Check for heap allocation failure.
(remoteConfigGetStringList): New function, based on code from Dan Berrangé.
(CHECK_TYPE): Remove macro.
(checkType): New function.
(GET_CONF_INT, GET_CONF_STR): New macros.
(remoteReadConfigFile): Use new macros to avoid duplication and to
check for allocation failure.
* src/conf.h (virConfTypeName): New static inline function.
2007-11-30 15:43:42 +00:00
free ( unix_sock_ro_perms ) ;
unix_sock_ro_perms = NULL ;
2007-09-19 02:28:01 +00:00
}
Detect heap allocation failure; factor out some duplication.
* qemud/qemud.c (tls_port, tcp_port, mdns_name, tls_allowed_ip_list):
(tls_allowed_dn_list): Remove "const", now that we free these.
(unix_sock_rw_mask): Rename from unix_sock_rw_perms, so that
the latter name can be used as a local string variable, so that the
variable name matches the config attribute name.
(unix_sock_ro_mask): Rename from unix_sock_ro_perms, likewise.
(remoteCheckDN, remoteCheckAccess): Adapt to const removal.
(qemudDispatchServer): Check for heap allocation failure.
(remoteConfigGetStringList): New function, based on code from Dan Berrangé.
(CHECK_TYPE): Remove macro.
(checkType): New function.
(GET_CONF_INT, GET_CONF_STR): New macros.
(remoteReadConfigFile): Use new macros to avoid duplication and to
check for allocation failure.
* src/conf.h (virConfTypeName): New static inline function.
2007-11-30 15:43:42 +00:00
GET_CONF_STR ( conf , filename , unix_sock_rw_perms ) ;
if ( unix_sock_rw_perms ) {
2008-02-08 09:15:16 +00:00
if ( virStrToLong_i ( unix_sock_rw_perms , NULL , 8 , & unix_sock_rw_mask ) ! = 0 ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " Failed to parse mode '%s' " ) , unix_sock_rw_perms ) ;
Detect heap allocation failure; factor out some duplication.
* qemud/qemud.c (tls_port, tcp_port, mdns_name, tls_allowed_ip_list):
(tls_allowed_dn_list): Remove "const", now that we free these.
(unix_sock_rw_mask): Rename from unix_sock_rw_perms, so that
the latter name can be used as a local string variable, so that the
variable name matches the config attribute name.
(unix_sock_ro_mask): Rename from unix_sock_ro_perms, likewise.
(remoteCheckDN, remoteCheckAccess): Adapt to const removal.
(qemudDispatchServer): Check for heap allocation failure.
(remoteConfigGetStringList): New function, based on code from Dan Berrangé.
(CHECK_TYPE): Remove macro.
(checkType): New function.
(GET_CONF_INT, GET_CONF_STR): New macros.
(remoteReadConfigFile): Use new macros to avoid duplication and to
check for allocation failure.
* src/conf.h (virConfTypeName): New static inline function.
2007-11-30 15:43:42 +00:00
goto free_and_fail ;
2007-09-19 02:28:01 +00:00
}
Detect heap allocation failure; factor out some duplication.
* qemud/qemud.c (tls_port, tcp_port, mdns_name, tls_allowed_ip_list):
(tls_allowed_dn_list): Remove "const", now that we free these.
(unix_sock_rw_mask): Rename from unix_sock_rw_perms, so that
the latter name can be used as a local string variable, so that the
variable name matches the config attribute name.
(unix_sock_ro_mask): Rename from unix_sock_ro_perms, likewise.
(remoteCheckDN, remoteCheckAccess): Adapt to const removal.
(qemudDispatchServer): Check for heap allocation failure.
(remoteConfigGetStringList): New function, based on code from Dan Berrangé.
(CHECK_TYPE): Remove macro.
(checkType): New function.
(GET_CONF_INT, GET_CONF_STR): New macros.
(remoteReadConfigFile): Use new macros to avoid duplication and to
check for allocation failure.
* src/conf.h (virConfTypeName): New static inline function.
2007-11-30 15:43:42 +00:00
free ( unix_sock_rw_perms ) ;
unix_sock_rw_perms = NULL ;
2007-09-19 02:28:01 +00:00
}
Detect heap allocation failure; factor out some duplication.
* qemud/qemud.c (tls_port, tcp_port, mdns_name, tls_allowed_ip_list):
(tls_allowed_dn_list): Remove "const", now that we free these.
(unix_sock_rw_mask): Rename from unix_sock_rw_perms, so that
the latter name can be used as a local string variable, so that the
variable name matches the config attribute name.
(unix_sock_ro_mask): Rename from unix_sock_ro_perms, likewise.
(remoteCheckDN, remoteCheckAccess): Adapt to const removal.
(qemudDispatchServer): Check for heap allocation failure.
(remoteConfigGetStringList): New function, based on code from Dan Berrangé.
(CHECK_TYPE): Remove macro.
(checkType): New function.
(GET_CONF_INT, GET_CONF_STR): New macros.
(remoteReadConfigFile): Use new macros to avoid duplication and to
check for allocation failure.
* src/conf.h (virConfTypeName): New static inline function.
2007-11-30 15:43:42 +00:00
GET_CONF_INT ( conf , filename , mdns_adv ) ;
GET_CONF_STR ( conf , filename , mdns_name ) ;
2007-09-19 01:56:55 +00:00
Detect heap allocation failure; factor out some duplication.
* qemud/qemud.c (tls_port, tcp_port, mdns_name, tls_allowed_ip_list):
(tls_allowed_dn_list): Remove "const", now that we free these.
(unix_sock_rw_mask): Rename from unix_sock_rw_perms, so that
the latter name can be used as a local string variable, so that the
variable name matches the config attribute name.
(unix_sock_ro_mask): Rename from unix_sock_ro_perms, likewise.
(remoteCheckDN, remoteCheckAccess): Adapt to const removal.
(qemudDispatchServer): Check for heap allocation failure.
(remoteConfigGetStringList): New function, based on code from Dan Berrangé.
(CHECK_TYPE): Remove macro.
(checkType): New function.
(GET_CONF_INT, GET_CONF_STR): New macros.
(remoteReadConfigFile): Use new macros to avoid duplication and to
check for allocation failure.
* src/conf.h (virConfTypeName): New static inline function.
2007-11-30 15:43:42 +00:00
GET_CONF_INT ( conf , filename , tls_no_verify_certificate ) ;
2007-06-11 12:04:54 +00:00
Detect heap allocation failure; factor out some duplication.
* qemud/qemud.c (tls_port, tcp_port, mdns_name, tls_allowed_ip_list):
(tls_allowed_dn_list): Remove "const", now that we free these.
(unix_sock_rw_mask): Rename from unix_sock_rw_perms, so that
the latter name can be used as a local string variable, so that the
variable name matches the config attribute name.
(unix_sock_ro_mask): Rename from unix_sock_ro_perms, likewise.
(remoteCheckDN, remoteCheckAccess): Adapt to const removal.
(qemudDispatchServer): Check for heap allocation failure.
(remoteConfigGetStringList): New function, based on code from Dan Berrangé.
(CHECK_TYPE): Remove macro.
(checkType): New function.
(GET_CONF_INT, GET_CONF_STR): New macros.
(remoteReadConfigFile): Use new macros to avoid duplication and to
check for allocation failure.
* src/conf.h (virConfTypeName): New static inline function.
2007-11-30 15:43:42 +00:00
GET_CONF_STR ( conf , filename , key_file ) ;
GET_CONF_STR ( conf , filename , cert_file ) ;
GET_CONF_STR ( conf , filename , ca_file ) ;
GET_CONF_STR ( conf , filename , crl_file ) ;
2007-06-11 12:04:54 +00:00
Detect heap allocation failure; factor out some duplication.
* qemud/qemud.c (tls_port, tcp_port, mdns_name, tls_allowed_ip_list):
(tls_allowed_dn_list): Remove "const", now that we free these.
(unix_sock_rw_mask): Rename from unix_sock_rw_perms, so that
the latter name can be used as a local string variable, so that the
variable name matches the config attribute name.
(unix_sock_ro_mask): Rename from unix_sock_ro_perms, likewise.
(remoteCheckDN, remoteCheckAccess): Adapt to const removal.
(qemudDispatchServer): Check for heap allocation failure.
(remoteConfigGetStringList): New function, based on code from Dan Berrangé.
(CHECK_TYPE): Remove macro.
(checkType): New function.
(GET_CONF_INT, GET_CONF_STR): New macros.
(remoteReadConfigFile): Use new macros to avoid duplication and to
check for allocation failure.
* src/conf.h (virConfTypeName): New static inline function.
2007-11-30 15:43:42 +00:00
if ( remoteConfigGetStringList ( conf , " tls_allowed_dn_list " ,
& tls_allowed_dn_list , filename ) < 0 )
goto free_and_fail ;
2007-06-11 12:04:54 +00:00
2007-12-05 19:25:44 +00:00
if ( remoteReadSaslAllowedUsernameList ( conf , server , filename ) < 0 )
Detect heap allocation failure; factor out some duplication.
* qemud/qemud.c (tls_port, tcp_port, mdns_name, tls_allowed_ip_list):
(tls_allowed_dn_list): Remove "const", now that we free these.
(unix_sock_rw_mask): Rename from unix_sock_rw_perms, so that
the latter name can be used as a local string variable, so that the
variable name matches the config attribute name.
(unix_sock_ro_mask): Rename from unix_sock_ro_perms, likewise.
(remoteCheckDN, remoteCheckAccess): Adapt to const removal.
(qemudDispatchServer): Check for heap allocation failure.
(remoteConfigGetStringList): New function, based on code from Dan Berrangé.
(CHECK_TYPE): Remove macro.
(checkType): New function.
(GET_CONF_INT, GET_CONF_STR): New macros.
(remoteReadConfigFile): Use new macros to avoid duplication and to
check for allocation failure.
* src/conf.h (virConfTypeName): New static inline function.
2007-11-30 15:43:42 +00:00
goto free_and_fail ;
2007-06-11 12:04:54 +00:00
2008-12-04 22:18:44 +00:00
GET_CONF_INT ( conf , filename , min_workers ) ;
GET_CONF_INT ( conf , filename , max_workers ) ;
GET_CONF_INT ( conf , filename , max_clients ) ;
Detect heap allocation failure; factor out some duplication.
* qemud/qemud.c (tls_port, tcp_port, mdns_name, tls_allowed_ip_list):
(tls_allowed_dn_list): Remove "const", now that we free these.
(unix_sock_rw_mask): Rename from unix_sock_rw_perms, so that
the latter name can be used as a local string variable, so that the
variable name matches the config attribute name.
(unix_sock_ro_mask): Rename from unix_sock_ro_perms, likewise.
(remoteCheckDN, remoteCheckAccess): Adapt to const removal.
(qemudDispatchServer): Check for heap allocation failure.
(remoteConfigGetStringList): New function, based on code from Dan Berrangé.
(CHECK_TYPE): Remove macro.
(checkType): New function.
(GET_CONF_INT, GET_CONF_STR): New macros.
(remoteReadConfigFile): Use new macros to avoid duplication and to
check for allocation failure.
* src/conf.h (virConfTypeName): New static inline function.
2007-11-30 15:43:42 +00:00
virConfFree ( conf ) ;
return 0 ;
2007-06-11 12:04:54 +00:00
Detect heap allocation failure; factor out some duplication.
* qemud/qemud.c (tls_port, tcp_port, mdns_name, tls_allowed_ip_list):
(tls_allowed_dn_list): Remove "const", now that we free these.
(unix_sock_rw_mask): Rename from unix_sock_rw_perms, so that
the latter name can be used as a local string variable, so that the
variable name matches the config attribute name.
(unix_sock_ro_mask): Rename from unix_sock_ro_perms, likewise.
(remoteCheckDN, remoteCheckAccess): Adapt to const removal.
(qemudDispatchServer): Check for heap allocation failure.
(remoteConfigGetStringList): New function, based on code from Dan Berrangé.
(CHECK_TYPE): Remove macro.
(checkType): New function.
(GET_CONF_INT, GET_CONF_STR): New macros.
(remoteReadConfigFile): Use new macros to avoid duplication and to
check for allocation failure.
* src/conf.h (virConfTypeName): New static inline function.
2007-11-30 15:43:42 +00:00
free_and_fail :
virConfFree ( conf ) ;
free ( mdns_name ) ;
mdns_name = NULL ;
free ( unix_sock_ro_perms ) ;
free ( unix_sock_rw_perms ) ;
free ( unix_sock_group ) ;
2008-05-14 20:57:20 +00:00
/* Don't bother trying to free listen_addr, tcp_port, tls_port, key_file,
cert_file , ca_file , or crl_file , since they are initialized to
non - malloc ' d strings . Besides , these are static variables , and callers
are unlikely to call this function more than once , so there wouldn ' t
Detect heap allocation failure; factor out some duplication.
* qemud/qemud.c (tls_port, tcp_port, mdns_name, tls_allowed_ip_list):
(tls_allowed_dn_list): Remove "const", now that we free these.
(unix_sock_rw_mask): Rename from unix_sock_rw_perms, so that
the latter name can be used as a local string variable, so that the
variable name matches the config attribute name.
(unix_sock_ro_mask): Rename from unix_sock_ro_perms, likewise.
(remoteCheckDN, remoteCheckAccess): Adapt to const removal.
(qemudDispatchServer): Check for heap allocation failure.
(remoteConfigGetStringList): New function, based on code from Dan Berrangé.
(CHECK_TYPE): Remove macro.
(checkType): New function.
(GET_CONF_INT, GET_CONF_STR): New macros.
(remoteReadConfigFile): Use new macros to avoid duplication and to
check for allocation failure.
* src/conf.h (virConfTypeName): New static inline function.
2007-11-30 15:43:42 +00:00
even be a real leak . */
if ( tls_allowed_dn_list ) {
int i ;
for ( i = 0 ; tls_allowed_dn_list [ i ] ; i + + )
free ( tls_allowed_dn_list [ i ] ) ;
free ( tls_allowed_dn_list ) ;
tls_allowed_dn_list = NULL ;
}
return - 1 ;
2007-06-11 12:04:54 +00:00
}
2008-12-12 07:56:50 +00:00
/* Display version information. */
static void
version ( const char * argv0 )
{
printf ( " %s (%s) %s \n " , argv0 , PACKAGE_NAME , PACKAGE_VERSION ) ;
}
2007-04-04 09:32:00 +00:00
/* Print command-line usage. */
static void
usage ( const char * argv0 )
{
fprintf ( stderr ,
2007-06-11 12:04:54 +00:00
" \n \
Usage : \ n \
% s [ options ] \ n \
\ n \
Options : \ n \
- v | - - verbose Verbose messages . \ n \
- d | - - daemon Run as a daemon & write PID file . \ n \
2007-06-26 23:48:46 +00:00
- l | - - listen Listen for TCP / IP connections . \ n \
- t | - - timeout < secs > Exit after timeout period . \ n \
2007-08-07 13:24:22 +00:00
- f | - - config < file > Configuration file . \ n \
2008-12-12 07:56:50 +00:00
| - - version Display version information . \ n \
2007-06-11 12:04:54 +00:00
- p | - - pid - file < file > Change name of PID file . \ n \
\ n \
2007-06-26 23:48:46 +00:00
libvirt management daemon : \ n \
2007-06-11 12:04:54 +00:00
\ n \
Default paths : \ n \
\ n \
2007-06-26 23:48:46 +00:00
Configuration file ( unless overridden by - c ) : \ n \
2007-06-11 12:04:54 +00:00
" SYSCONF_DIR " / libvirt / libvirtd . conf \ n \
\ n \
2007-06-26 23:48:46 +00:00
Sockets ( as root ) : \ n \
2007-06-11 12:04:54 +00:00
" LOCAL_STATE_DIR " / run / libvirt / libvirt - sock \ n \
" LOCAL_STATE_DIR " / run / libvirt / libvirt - sock - ro \ n \
2007-06-26 23:48:46 +00:00
\ n \
Sockets ( as non - root ) : \ n \
$ HOME / . libvirt / libvirt - sock ( in UNIX abstract namespace ) \ n \
2007-06-11 12:04:54 +00:00
\ n \
TLS : \ n \
CA certificate : " LIBVIRT_CACERT " \ n \
Server certificate : " LIBVIRT_SERVERCERT " \ n \
Server private key : " LIBVIRT_SERVERKEY " \ n \
\ n \
PID file ( unless overridden by - - pid - file ) : \ n \
% s \ n \
\ n " ,
argv0 ,
REMOTE_PID_FILE [ 0 ] ! = ' \0 '
? REMOTE_PID_FILE
: " (disabled in ./configure) " ) ;
2007-04-04 09:32:00 +00:00
}
2008-12-12 07:56:50 +00:00
enum {
OPT_VERSION = 129
} ;
2007-02-14 01:40:09 +00:00
# define MAX_LISTEN 5
int main ( int argc , char * * argv ) {
2008-03-03 18:10:19 +00:00
struct qemud_server * server = NULL ;
2007-02-16 18:28:17 +00:00
struct sigaction sig_action ;
int sigpipe [ 2 ] ;
2007-06-11 12:04:54 +00:00
const char * pid_file = NULL ;
2009-01-12 18:22:32 +00:00
const char * remote_config_file = NULL ;
2007-02-23 12:48:36 +00:00
int ret = 1 ;
2007-02-14 01:40:09 +00:00
struct option opts [ ] = {
{ " verbose " , no_argument , & verbose , 1 } ,
{ " daemon " , no_argument , & godaemon , 1 } ,
2007-06-26 23:48:46 +00:00
{ " listen " , no_argument , & ipsock , 1 } ,
2007-08-07 13:24:22 +00:00
{ " config " , required_argument , NULL , ' f ' } ,
2007-04-04 09:32:00 +00:00
{ " timeout " , required_argument , NULL , ' t ' } ,
{ " pid-file " , required_argument , NULL , ' p ' } ,
2008-12-12 07:56:50 +00:00
{ " version " , no_argument , NULL , OPT_VERSION } ,
2007-04-04 09:32:00 +00:00
{ " help " , no_argument , NULL , ' ? ' } ,
2007-02-14 01:40:09 +00:00
{ 0 , 0 , 0 , 0 }
} ;
while ( 1 ) {
int optidx = 0 ;
int c ;
char * tmp ;
2007-08-07 13:24:22 +00:00
c = getopt_long ( argc , argv , " ldf:p:t:v " , opts , & optidx ) ;
2007-02-14 01:40:09 +00:00
if ( c = = - 1 ) {
break ;
}
switch ( c ) {
case 0 :
/* Got one of the flags */
break ;
case ' v ' :
verbose = 1 ;
break ;
case ' d ' :
godaemon = 1 ;
break ;
2007-06-26 23:48:46 +00:00
case ' l ' :
ipsock = 1 ;
2007-02-14 01:40:09 +00:00
break ;
case ' t ' :
2008-02-08 09:15:16 +00:00
if ( virStrToLong_i ( optarg , & tmp , 10 , & timeout ) ! = 0
2007-11-14 10:53:05 +00:00
| | timeout < = 0
/* Ensure that we can multiply by 1000 without overflowing. */
| | timeout > INT_MAX / 1000 )
2007-02-14 01:40:09 +00:00
timeout = - 1 ;
break ;
2007-02-23 12:48:36 +00:00
case ' p ' :
2007-06-11 12:04:54 +00:00
pid_file = optarg ;
break ;
case ' f ' :
remote_config_file = optarg ;
2007-02-23 12:48:36 +00:00
break ;
2008-12-12 07:56:50 +00:00
case OPT_VERSION :
version ( argv [ 0 ] ) ;
return 0 ;
2007-02-14 01:40:09 +00:00
case ' ? ' :
2007-04-04 09:32:00 +00:00
usage ( argv [ 0 ] ) ;
2007-02-14 01:40:09 +00:00
return 2 ;
default :
2007-08-07 13:24:22 +00:00
fprintf ( stderr , " libvirtd: internal error: unknown flag: %c \n " ,
c ) ;
exit ( 1 ) ;
2007-02-14 01:40:09 +00:00
}
}
2009-01-12 18:22:32 +00:00
if ( remote_config_file = = NULL ) {
static const char * default_config_file
= SYSCONF_DIR " /libvirt/libvirtd.conf " ;
remote_config_file =
2009-01-13 12:22:24 +00:00
( access ( default_config_file , R_OK ) = = 0
2009-01-12 18:22:32 +00:00
? default_config_file
: " /dev/null " ) ;
}
2008-05-20 16:17:36 +00:00
if ( godaemon ) {
if ( qemudGoDaemon ( ) < 0 ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " Failed to fork as daemon: %s " ) , strerror ( errno ) ) ;
2008-05-20 16:17:36 +00:00
goto error1 ;
}
}
/* If running as root and no PID file is set, use the default */
if ( pid_file = = NULL & &
getuid ( ) = = 0 & &
REMOTE_PID_FILE [ 0 ] ! = ' \0 ' )
pid_file = REMOTE_PID_FILE ;
/* If we have a pidfile set, claim it now, exiting if already taken */
if ( pid_file ! = NULL & &
qemudWritePidFile ( pid_file ) < 0 )
goto error1 ;
2007-02-16 18:28:17 +00:00
if ( pipe ( sigpipe ) < 0 | |
qemudSetNonBlock ( sigpipe [ 0 ] ) < 0 | |
2008-02-20 15:47:06 +00:00
qemudSetNonBlock ( sigpipe [ 1 ] ) < 0 | |
qemudSetCloseExec ( sigpipe [ 0 ] ) < 0 | |
qemudSetCloseExec ( sigpipe [ 1 ] ) < 0 ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " Failed to create pipe: %s " ) , strerror ( errno ) ) ;
2008-05-20 16:17:36 +00:00
goto error2 ;
2007-02-16 18:30:55 +00:00
}
2007-02-16 18:28:17 +00:00
sigwrite = sigpipe [ 1 ] ;
2008-05-20 16:17:36 +00:00
sig_action . sa_sigaction = sig_handler ;
sig_action . sa_flags = SA_SIGINFO ;
sigemptyset ( & sig_action . sa_mask ) ;
sigaction ( SIGHUP , & sig_action , NULL ) ;
sigaction ( SIGINT , & sig_action , NULL ) ;
sigaction ( SIGQUIT , & sig_action , NULL ) ;
sigaction ( SIGTERM , & sig_action , NULL ) ;
sigaction ( SIGCHLD , & sig_action , NULL ) ;
sig_action . sa_handler = SIG_IGN ;
sigaction ( SIGPIPE , & sig_action , NULL ) ;
2007-12-05 15:34:05 +00:00
if ( ! ( server = qemudInitialize ( sigpipe [ 0 ] ) ) ) {
ret = 2 ;
2008-05-20 16:17:36 +00:00
goto error2 ;
2007-12-05 15:34:05 +00:00
}
2007-02-16 18:28:17 +00:00
2007-12-05 15:34:05 +00:00
/* Read the config file (if it exists). */
if ( remoteReadConfigFile ( server , remote_config_file ) < 0 )
2008-05-20 16:17:36 +00:00
goto error2 ;
2007-02-14 01:40:09 +00:00
2008-04-25 15:46:46 +00:00
/* Change the group ownership of /var/run/libvirt to unix_sock_gid */
2008-05-20 16:17:36 +00:00
if ( getuid ( ) = = 0 ) {
2008-04-25 15:46:46 +00:00
const char * sockdirname = LOCAL_STATE_DIR " /run/libvirt " ;
if ( chown ( sockdirname , - 1 , unix_sock_gid ) < 0 )
2009-01-06 18:32:03 +00:00
VIR_ERROR ( _ ( " Failed to change group ownership of %s " ) , sockdirname ) ;
2008-04-25 15:46:46 +00:00
}
2007-06-26 22:51:01 +00:00
if ( virEventAddHandleImpl ( sigpipe [ 0 ] ,
2008-10-23 13:18:18 +00:00
VIR_EVENT_HANDLE_READABLE ,
2007-06-26 22:51:01 +00:00
qemudDispatchSignalEvent ,
2008-11-19 16:24:01 +00:00
server , NULL ) < 0 ) {
2009-01-06 18:32:03 +00:00
VIR_ERROR0 ( _ ( " Failed to register callback for signal pipe " ) ) ;
2007-06-26 19:11:00 +00:00
ret = 3 ;
goto error2 ;
}
2007-12-05 15:34:05 +00:00
if ( ! ( server = qemudNetworkInit ( server ) ) ) {
ret = 2 ;
goto error2 ;
}
2007-06-11 12:04:54 +00:00
qemudRunLoop ( server ) ;
2007-02-14 01:40:09 +00:00
2007-02-23 12:48:36 +00:00
ret = 0 ;
2008-05-20 16:17:36 +00:00
error2 :
2008-03-03 18:10:19 +00:00
if ( server )
qemudCleanup ( server ) ;
2008-05-20 16:17:36 +00:00
if ( pid_file )
unlink ( pid_file ) ;
close ( sigwrite ) ;
error1 :
2008-12-22 12:53:26 +00:00
virLogShutdown ( ) ;
2007-02-23 12:48:36 +00:00
return ret ;
2007-02-14 01:40:09 +00:00
}