2012-04-04 16:09:09 +04:00
/*
2014-03-07 17:38:51 +04:00
* libvirtd - config . c : daemon start of day , guest process & i / o management
2012-04-04 16:09:09 +04:00
*
2014-03-18 12:19:33 +04:00
* Copyright ( C ) 2006 - 2012 , 2014 Red Hat , Inc .
2012-04-04 16:09:09 +04: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
2012-09-21 02:30:55 +04:00
* License along with this library . If not , see
2012-07-21 14:06:23 +04:00
* < http : //www.gnu.org/licenses/>.
2012-04-04 16:09:09 +04:00
*
* Author : Daniel P . Berrange < berrange @ redhat . com >
*/
# include <config.h>
# include "libvirtd-config.h"
2012-12-12 20:35:35 +04:00
# include "virconf.h"
2012-12-12 22:06:53 +04:00
# include "viralloc.h"
2012-12-13 22:21:53 +04:00
# include "virerror.h"
2012-12-12 21:59:27 +04:00
# include "virlog.h"
2012-04-04 18:00:17 +04:00
# include "rpc/virnetserver.h"
2012-04-04 16:09:09 +04:00
# include "configmake.h"
2012-04-04 18:00:17 +04:00
# include "remote/remote_protocol.h"
# include "remote/remote_driver.h"
2013-04-03 14:36:23 +04:00
# include "virstring.h"
# include "virutil.h"
2012-04-04 16:09:09 +04:00
# define VIR_FROM_THIS VIR_FROM_CONF
2014-02-28 16:16:17 +04:00
VIR_LOG_INIT ( " daemon.libvirtd-config " ) ;
2012-04-04 16:09:09 +04: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 ;
2012-10-17 13:23:12 +04:00
virConfValuePtr p = virConfGetValue ( conf , key ) ;
2012-04-04 16:09:09 +04:00
if ( ! p )
return 0 ;
switch ( p - > type ) {
case VIR_CONF_STRING :
if ( VIR_ALLOC_N ( list , 2 ) < 0 ) {
2012-07-18 22:26:35 +04:00
virReportError ( VIR_ERR_CONFIG_UNSUPPORTED ,
_ ( " failed to allocate memory for %s config list " ) ,
key ) ;
2012-04-04 16:09:09 +04:00
return - 1 ;
}
2013-05-03 16:39:39 +04:00
if ( VIR_STRDUP ( list [ 0 ] , p - > str ) < 0 ) {
2012-04-04 16:09:09 +04:00
VIR_FREE ( list ) ;
return - 1 ;
}
2013-05-03 16:39:39 +04:00
list [ 1 ] = NULL ;
2012-04-04 16:09:09 +04:00
break ;
case VIR_CONF_LIST : {
Convert 'int i' to 'size_t i' in daemon/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 18:09:33 +04:00
int len = 0 ;
size_t i ;
2012-04-04 16:09:09 +04:00
virConfValuePtr pp ;
for ( pp = p - > list ; pp ; pp = pp - > next )
len + + ;
if ( VIR_ALLOC_N ( list , 1 + len ) < 0 ) {
2012-07-18 22:26:35 +04:00
virReportError ( VIR_ERR_CONFIG_UNSUPPORTED ,
_ ( " failed to allocate memory for %s config list " ) ,
key ) ;
2012-04-04 16:09:09 +04:00
return - 1 ;
}
for ( i = 0 , pp = p - > list ; pp ; + + i , pp = pp - > next ) {
if ( pp - > type ! = VIR_CONF_STRING ) {
2012-07-18 22:26:35 +04:00
virReportError ( VIR_ERR_CONFIG_UNSUPPORTED ,
_ ( " remoteReadConfigFile: %s: %s: "
" must be a string or list of strings " ) ,
filename , key ) ;
2012-04-04 16:09:09 +04:00
VIR_FREE ( list ) ;
return - 1 ;
}
2013-05-03 16:39:39 +04:00
if ( VIR_STRDUP ( list [ i ] , pp - > str ) < 0 ) {
Convert 'int i' to 'size_t i' in daemon/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 18:09:33 +04:00
size_t j ;
2013-05-21 11:45:26 +04:00
for ( j = 0 ; j < i ; j + + )
2012-04-04 16:09:09 +04:00
VIR_FREE ( list [ j ] ) ;
VIR_FREE ( list ) ;
return - 1 ;
}
}
list [ i ] = NULL ;
break ;
}
default :
2012-07-18 22:26:35 +04:00
virReportError ( VIR_ERR_CONFIG_UNSUPPORTED ,
_ ( " remoteReadConfigFile: %s: %s: "
" must be a string or list of strings " ) ,
filename , key ) ;
2012-04-04 16:09:09 +04:00
return - 1 ;
}
* list_arg = list ;
return 0 ;
}
/* A helper function used by each of the following macros. */
static int
2012-10-17 13:23:12 +04:00
checkType ( virConfValuePtr p , const char * filename ,
const char * key , virConfType required_type )
2012-04-04 16:09:09 +04:00
{
if ( p - > type ! = required_type ) {
2012-07-18 22:26:35 +04:00
virReportError ( VIR_ERR_CONFIG_UNSUPPORTED ,
_ ( " remoteReadConfigFile: %s: %s: invalid type: "
" got %s; expected %s " ) , filename , key ,
2014-12-09 16:53:28 +03:00
virConfTypeToString ( p - > type ) ,
virConfTypeToString ( required_type ) ) ;
2012-04-04 16:09:09 +04:00
return - 1 ;
}
return 0 ;
}
/* If there is no config data for the key, #var_name, then do nothing.
2013-05-03 16:39:39 +04:00
If there is valid data of type VIR_CONF_STRING , and VIR_STRDUP succeeds ,
store the result in var_name . Otherwise , ( i . e . invalid type , or VIR_STRDUP
2012-04-04 16:09:09 +04:00
failure ) , give a diagnostic and " goto " the cleanup - and - fail label . */
# define GET_CONF_STR(conf, filename, var_name) \
do { \
2012-10-17 13:23:12 +04:00
virConfValuePtr p = virConfGetValue ( conf , # var_name ) ; \
2012-04-04 16:09:09 +04:00
if ( p ) { \
2012-10-17 13:23:12 +04:00
if ( checkType ( p , filename , # var_name , VIR_CONF_STRING ) < 0 ) \
2012-04-04 16:09:09 +04:00
goto error ; \
VIR_FREE ( data - > var_name ) ; \
2013-05-03 16:39:39 +04:00
if ( VIR_STRDUP ( data - > var_name , p - > str ) < 0 ) \
2012-04-04 16:09:09 +04:00
goto error ; \
} \
} while ( 0 )
2014-12-09 18:22:09 +03:00
/* Like GET_CONF_STR, but for signed integral values. */
2012-04-04 16:09:09 +04:00
# define GET_CONF_INT(conf, filename, var_name) \
do { \
2012-10-17 13:23:12 +04:00
virConfValuePtr p = virConfGetValue ( conf , # var_name ) ; \
2012-04-04 16:09:09 +04:00
if ( p ) { \
2014-12-09 18:22:09 +03:00
if ( p - > type ! = VIR_CONF_ULONG & & \
checkType ( p , filename , # var_name , VIR_CONF_LONG ) < 0 ) \
2012-04-04 16:09:09 +04:00
goto error ; \
data - > var_name = p - > l ; \
} \
} while ( 0 )
2014-12-09 18:22:09 +03:00
/* Like GET_CONF_STR, but for unsigned integral values. */
# define GET_CONF_UINT(conf, filename, var_name) \
do { \
virConfValuePtr p = virConfGetValue ( conf , # var_name ) ; \
if ( p ) { \
if ( checkType ( p , filename , # var_name , VIR_CONF_ULONG ) < 0 ) \
goto error ; \
data - > var_name = p - > l ; \
} \
} while ( 0 )
2012-04-04 16:09:09 +04:00
2014-03-18 12:19:33 +04:00
static int
remoteConfigGetAuth ( virConfPtr conf ,
const char * key ,
int * auth ,
const char * filename )
{
2012-04-04 16:09:09 +04:00
virConfValuePtr p ;
2012-10-17 13:23:12 +04:00
p = virConfGetValue ( conf , key ) ;
2012-04-04 16:09:09 +04:00
if ( ! p )
return 0 ;
2012-10-17 13:23:12 +04:00
if ( checkType ( p , filename , key , VIR_CONF_STRING ) < 0 )
2012-04-04 16:09:09 +04:00
return - 1 ;
if ( ! p - > str )
return 0 ;
if ( STREQ ( p - > str , " none " ) ) {
* auth = VIR_NET_SERVER_SERVICE_AUTH_NONE ;
2012-09-20 15:58:29 +04:00
# if WITH_SASL
2012-04-04 16:09:09 +04:00
} else if ( STREQ ( p - > str , " sasl " ) ) {
* auth = VIR_NET_SERVER_SERVICE_AUTH_SASL ;
# endif
} else if ( STREQ ( p - > str , " polkit " ) ) {
* auth = VIR_NET_SERVER_SERVICE_AUTH_POLKIT ;
} else {
2012-07-18 22:26:35 +04:00
virReportError ( VIR_ERR_CONFIG_UNSUPPORTED ,
_ ( " remoteReadConfigFile: %s: %s: unsupported auth %s " ) ,
filename , key , p - > str ) ;
2012-04-04 16:09:09 +04:00
return - 1 ;
}
return 0 ;
}
int
daemonConfigFilePath ( bool privileged , char * * configfile )
{
if ( privileged ) {
2013-05-03 16:39:39 +04:00
if ( VIR_STRDUP ( * configfile , SYSCONFDIR " /libvirt/libvirtd.conf " ) < 0 )
goto error ;
2012-04-04 16:09:09 +04:00
} else {
2012-05-03 20:36:27 +04:00
char * configdir = NULL ;
2012-04-04 16:09:09 +04:00
2012-05-24 16:29:42 +04:00
if ( ! ( configdir = virGetUserConfigDirectory ( ) ) )
2012-04-04 16:09:09 +04:00
goto error ;
2012-05-03 20:36:27 +04:00
if ( virAsprintf ( configfile , " %s/libvirtd.conf " , configdir ) < 0 ) {
VIR_FREE ( configdir ) ;
2013-07-04 13:58:18 +04:00
goto error ;
2012-04-04 16:09:09 +04:00
}
2012-05-03 20:36:27 +04:00
VIR_FREE ( configdir ) ;
2012-04-04 16:09:09 +04:00
}
return 0 ;
2014-03-25 10:45:38 +04:00
error :
2012-04-04 16:09:09 +04:00
return - 1 ;
}
struct daemonConfig *
daemonConfigNew ( bool privileged ATTRIBUTE_UNUSED )
{
struct daemonConfig * data ;
char * localhost ;
int ret ;
2013-07-04 13:58:18 +04:00
if ( VIR_ALLOC ( data ) < 0 )
2012-04-04 16:09:09 +04:00
return NULL ;
data - > listen_tls = 1 ;
data - > listen_tcp = 0 ;
2013-05-03 16:39:39 +04:00
if ( VIR_STRDUP ( data - > tls_port , LIBVIRTD_TLS_PORT ) < 0 | |
VIR_STRDUP ( data - > tcp_port , LIBVIRTD_TCP_PORT ) < 0 )
goto error ;
2012-04-04 16:09:09 +04:00
/* Only default to PolicyKit if running as root */
2013-01-09 02:19:00 +04:00
# if WITH_POLKIT
2012-04-04 16:09:09 +04:00
if ( privileged ) {
data - > auth_unix_rw = REMOTE_AUTH_POLKIT ;
data - > auth_unix_ro = REMOTE_AUTH_POLKIT ;
} else {
# endif
data - > auth_unix_rw = REMOTE_AUTH_NONE ;
data - > auth_unix_ro = REMOTE_AUTH_NONE ;
2013-01-09 02:19:00 +04:00
# if WITH_POLKIT
2012-04-04 16:09:09 +04:00
}
# endif
2013-05-03 16:39:39 +04:00
if ( VIR_STRDUP ( data - > unix_sock_rw_perms ,
data - > auth_unix_rw = = REMOTE_AUTH_POLKIT ? " 0777 " : " 0700 " ) < 0 | |
VIR_STRDUP ( data - > unix_sock_ro_perms , " 0777 " ) < 0 )
goto error ;
2012-04-04 16:09:09 +04:00
2012-09-20 15:58:29 +04:00
# if WITH_SASL
2012-04-04 16:09:09 +04:00
data - > auth_tcp = REMOTE_AUTH_SASL ;
# else
data - > auth_tcp = REMOTE_AUTH_NONE ;
# endif
data - > auth_tls = REMOTE_AUTH_NONE ;
data - > mdns_adv = 0 ;
data - > min_workers = 5 ;
data - > max_workers = 20 ;
2014-03-04 21:55:24 +04:00
data - > max_clients = 5000 ;
data - > max_anonymous_clients = 20 ;
2012-04-04 16:09:09 +04:00
data - > prio_workers = 5 ;
data - > max_requests = 20 ;
data - > max_client_requests = 5 ;
data - > audit_level = 1 ;
data - > audit_logging = 0 ;
data - > keepalive_interval = 5 ;
data - > keepalive_count = 5 ;
data - > keepalive_required = 0 ;
2013-04-26 20:39:11 +04:00
localhost = virGetHostname ( ) ;
2012-04-04 16:09:09 +04:00
if ( localhost = = NULL ) {
/* we couldn't resolve the hostname; assume that we are
* running in disconnected operation , and report a less
* useful Avahi string
*/
2013-06-07 17:20:35 +04:00
ret = VIR_STRDUP ( data - > mdns_name , " Virtualization Host " ) ;
2012-04-04 16:09:09 +04:00
} else {
char * tmp ;
/* Extract the host part of the potentially FQDN */
if ( ( tmp = strchr ( localhost , ' . ' ) ) )
* tmp = ' \0 ' ;
ret = virAsprintf ( & data - > mdns_name , " Virtualization Host %s " ,
localhost ) ;
}
VIR_FREE ( localhost ) ;
if ( ret < 0 )
2013-07-04 13:58:18 +04:00
goto error ;
2012-04-04 16:09:09 +04:00
return data ;
2014-03-25 10:45:38 +04:00
error :
2012-04-04 16:09:09 +04:00
daemonConfigFree ( data ) ;
return NULL ;
}
void
daemonConfigFree ( struct daemonConfig * data )
{
char * * tmp ;
if ( ! data )
return ;
VIR_FREE ( data - > listen_addr ) ;
VIR_FREE ( data - > tls_port ) ;
VIR_FREE ( data - > tcp_port ) ;
2013-06-28 21:10:10 +04:00
tmp = data - > access_drivers ;
while ( tmp & & * tmp ) {
VIR_FREE ( * tmp ) ;
tmp + + ;
}
VIR_FREE ( data - > access_drivers ) ;
2012-04-04 16:09:09 +04:00
VIR_FREE ( data - > unix_sock_ro_perms ) ;
VIR_FREE ( data - > unix_sock_rw_perms ) ;
VIR_FREE ( data - > unix_sock_group ) ;
VIR_FREE ( data - > unix_sock_dir ) ;
VIR_FREE ( data - > mdns_name ) ;
tmp = data - > tls_allowed_dn_list ;
while ( tmp & & * tmp ) {
VIR_FREE ( * tmp ) ;
tmp + + ;
}
VIR_FREE ( data - > tls_allowed_dn_list ) ;
tmp = data - > sasl_allowed_username_list ;
while ( tmp & & * tmp ) {
VIR_FREE ( * tmp ) ;
tmp + + ;
}
VIR_FREE ( data - > sasl_allowed_username_list ) ;
VIR_FREE ( data - > key_file ) ;
VIR_FREE ( data - > ca_file ) ;
VIR_FREE ( data - > cert_file ) ;
VIR_FREE ( data - > crl_file ) ;
2012-04-12 13:10:42 +04:00
VIR_FREE ( data - > host_uuid ) ;
2012-04-04 16:09:09 +04:00
VIR_FREE ( data - > log_filters ) ;
VIR_FREE ( data - > log_outputs ) ;
VIR_FREE ( data ) ;
}
2012-04-04 16:14:19 +04:00
static int
daemonConfigLoadOptions ( struct daemonConfig * data ,
const char * filename ,
virConfPtr conf )
2012-04-04 16:09:09 +04:00
{
2014-12-09 18:22:09 +03:00
GET_CONF_UINT ( conf , filename , listen_tcp ) ;
GET_CONF_UINT ( conf , filename , listen_tls ) ;
2012-10-17 13:23:12 +04:00
GET_CONF_STR ( conf , filename , tls_port ) ;
GET_CONF_STR ( conf , filename , tcp_port ) ;
GET_CONF_STR ( conf , filename , listen_addr ) ;
2012-04-04 16:09:09 +04:00
if ( remoteConfigGetAuth ( conf , " auth_unix_rw " , & data - > auth_unix_rw , filename ) < 0 )
goto error ;
2013-01-09 02:19:00 +04:00
# if WITH_POLKIT
2012-04-04 16:09:09 +04:00
/* Change default perms to be wide-open if PolicyKit is enabled.
* Admin can always override in config file
*/
if ( data - > auth_unix_rw = = REMOTE_AUTH_POLKIT ) {
VIR_FREE ( data - > unix_sock_rw_perms ) ;
2013-05-03 16:39:39 +04:00
if ( VIR_STRDUP ( data - > unix_sock_rw_perms , " 0777 " ) < 0 )
2012-04-04 16:09:09 +04:00
goto error ;
}
# endif
if ( remoteConfigGetAuth ( conf , " auth_unix_ro " , & data - > auth_unix_ro , filename ) < 0 )
goto error ;
if ( remoteConfigGetAuth ( conf , " auth_tcp " , & data - > auth_tcp , filename ) < 0 )
goto error ;
if ( remoteConfigGetAuth ( conf , " auth_tls " , & data - > auth_tls , filename ) < 0 )
goto error ;
2013-04-17 15:01:24 +04:00
if ( remoteConfigGetStringList ( conf , " access_drivers " ,
& data - > access_drivers , filename ) < 0 )
goto error ;
2012-10-17 13:23:12 +04:00
GET_CONF_STR ( conf , filename , unix_sock_group ) ;
GET_CONF_STR ( conf , filename , unix_sock_ro_perms ) ;
GET_CONF_STR ( conf , filename , unix_sock_rw_perms ) ;
2012-04-04 16:09:09 +04:00
2012-10-17 13:23:12 +04:00
GET_CONF_STR ( conf , filename , unix_sock_dir ) ;
2012-04-04 16:09:09 +04:00
2014-12-09 18:22:09 +03:00
GET_CONF_UINT ( conf , filename , mdns_adv ) ;
2012-10-17 13:23:12 +04:00
GET_CONF_STR ( conf , filename , mdns_name ) ;
2012-04-04 16:09:09 +04:00
2014-12-09 18:22:09 +03:00
GET_CONF_UINT ( conf , filename , tls_no_sanity_certificate ) ;
GET_CONF_UINT ( conf , filename , tls_no_verify_certificate ) ;
2012-04-04 16:09:09 +04:00
2012-10-17 13:23:12 +04: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 ) ;
2012-04-04 16:09:09 +04:00
if ( remoteConfigGetStringList ( conf , " tls_allowed_dn_list " ,
& data - > tls_allowed_dn_list , filename ) < 0 )
goto error ;
if ( remoteConfigGetStringList ( conf , " sasl_allowed_username_list " ,
& data - > sasl_allowed_username_list , filename ) < 0 )
goto error ;
2014-12-09 18:22:09 +03:00
GET_CONF_UINT ( conf , filename , min_workers ) ;
GET_CONF_UINT ( conf , filename , max_workers ) ;
GET_CONF_UINT ( conf , filename , max_clients ) ;
GET_CONF_UINT ( conf , filename , max_queued_clients ) ;
GET_CONF_UINT ( conf , filename , max_anonymous_clients ) ;
2012-04-04 16:09:09 +04:00
2014-12-09 18:22:09 +03:00
GET_CONF_UINT ( conf , filename , prio_workers ) ;
2012-04-04 16:09:09 +04:00
2012-10-17 13:23:12 +04:00
GET_CONF_INT ( conf , filename , max_requests ) ;
2014-12-09 18:22:09 +03:00
GET_CONF_UINT ( conf , filename , max_client_requests ) ;
2012-04-04 16:09:09 +04:00
2014-12-09 18:22:09 +03:00
GET_CONF_UINT ( conf , filename , audit_level ) ;
GET_CONF_UINT ( conf , filename , audit_logging ) ;
2012-04-04 16:09:09 +04:00
2012-10-17 13:23:12 +04:00
GET_CONF_STR ( conf , filename , host_uuid ) ;
2012-04-04 16:09:09 +04:00
2014-12-09 18:22:09 +03:00
GET_CONF_UINT ( conf , filename , log_level ) ;
2012-10-17 13:23:12 +04:00
GET_CONF_STR ( conf , filename , log_filters ) ;
GET_CONF_STR ( conf , filename , log_outputs ) ;
2012-04-04 16:09:09 +04:00
2012-10-17 13:23:12 +04:00
GET_CONF_INT ( conf , filename , keepalive_interval ) ;
2014-12-09 18:22:09 +03:00
GET_CONF_UINT ( conf , filename , keepalive_count ) ;
GET_CONF_UINT ( conf , filename , keepalive_required ) ;
2012-04-04 16:09:09 +04:00
return 0 ;
2014-03-25 10:45:38 +04:00
error :
2012-04-04 16:09:09 +04:00
return - 1 ;
}
2012-04-04 16:14:19 +04:00
/* Read the config file if it exists.
* Only used in the remote case , hence the name .
*/
int
daemonConfigLoadFile ( struct daemonConfig * data ,
const char * filename ,
bool allow_missing )
{
virConfPtr conf ;
int ret ;
if ( allow_missing & &
access ( filename , R_OK ) = = - 1 & &
errno = = ENOENT )
return 0 ;
conf = virConfReadFile ( filename , 0 ) ;
if ( ! conf )
return - 1 ;
ret = daemonConfigLoadOptions ( data , filename , conf ) ;
virConfFree ( conf ) ;
return ret ;
}
int daemonConfigLoadData ( struct daemonConfig * data ,
const char * filename ,
const char * filedata )
{
virConfPtr conf ;
int ret ;
conf = virConfReadMem ( filedata , strlen ( filedata ) , 0 ) ;
if ( ! conf )
return - 1 ;
ret = daemonConfigLoadOptions ( data , filename , conf ) ;
virConfFree ( conf ) ;
return ret ;
}