提交 54628f54 编写于 作者: D Daniel P. Berrange

libvirtd: convert to typesafe virConf accessors

The libvirtdconftest was previously used to test data type
handling of the libvirtd config file. Now we're using the
typedef APIs, this test case has little value, and is pretty
hard to fixup with deal with the new APIs.
Signed-off-by: NDaniel P. Berrange <berrange@redhat.com>
上级 6381c89f
......@@ -39,171 +39,38 @@
VIR_LOG_INIT("daemon.libvirtd-config");
/* 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:
if (VIR_ALLOC_N(list, 2) < 0) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("failed to allocate memory for %s config list"),
key);
return -1;
}
if (VIR_STRDUP(list[0], p->str) < 0) {
VIR_FREE(list);
return -1;
}
list[1] = NULL;
break;
case VIR_CONF_LIST: {
int len = 0;
size_t i;
virConfValuePtr pp;
for (pp = p->list; pp; pp = pp->next)
len++;
if (VIR_ALLOC_N(list, 1+len) < 0) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("failed to allocate memory for %s config list"),
key);
return -1;
}
for (i = 0, pp = p->list; pp; ++i, pp = pp->next) {
if (pp->type != VIR_CONF_STRING) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("remoteReadConfigFile: %s: %s:"
" must be a string or list of strings"),
filename, key);
VIR_FREE(list);
return -1;
}
if (VIR_STRDUP(list[i], pp->str) < 0) {
size_t j;
for (j = 0; j < i; j++)
VIR_FREE(list[j]);
VIR_FREE(list);
return -1;
}
}
list[i] = NULL;
break;
}
default:
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("remoteReadConfigFile: %s: %s:"
" must be a string or list of strings"),
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) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("remoteReadConfigFile: %s: %s: invalid type:"
" got %s; expected %s"), filename, key,
virConfTypeToString(p->type),
virConfTypeToString(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 VIR_STRDUP succeeds,
store the result in var_name. Otherwise, (i.e. invalid type, or VIR_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 error; \
VIR_FREE(data->var_name); \
if (VIR_STRDUP(data->var_name, p->str) < 0) \
goto error; \
} \
} while (0)
/* Like GET_CONF_STR, but for signed integral values. */
#define GET_CONF_INT(conf, filename, var_name) \
do { \
virConfValuePtr p = virConfGetValue(conf, #var_name); \
if (p) { \
if (p->type != VIR_CONF_ULONG && \
checkType(p, filename, #var_name, VIR_CONF_LONG) < 0) \
goto error; \
data->var_name = p->l; \
} \
} while (0)
/* 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)
static int
remoteConfigGetAuth(virConfPtr conf,
const char *filename,
const char *key,
int *auth,
const char *filename)
int *auth)
{
virConfValuePtr p;
p = virConfGetValue(conf, key);
if (!p)
return 0;
char *authstr = NULL;
if (checkType(p, filename, key, VIR_CONF_STRING) < 0)
if (virConfGetValueString(conf, key, &authstr) < 0)
return -1;
if (!p->str)
if (!authstr)
return 0;
if (STREQ(p->str, "none")) {
if (STREQ(authstr, "none")) {
*auth = VIR_NET_SERVER_SERVICE_AUTH_NONE;
#if WITH_SASL
} else if (STREQ(p->str, "sasl")) {
} else if (STREQ(authstr, "sasl")) {
*auth = VIR_NET_SERVER_SERVICE_AUTH_SASL;
#endif
} else if (STREQ(p->str, "polkit")) {
} else if (STREQ(authstr, "polkit")) {
*auth = VIR_NET_SERVER_SERVICE_AUTH_POLKIT;
} else {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("remoteReadConfigFile: %s: %s: unsupported auth %s"),
filename, key, p->str);
_("%s: %s: unsupported auth %s"),
filename, key, authstr);
VIR_FREE(authstr);
return -1;
}
VIR_FREE(authstr);
return 0;
}
......@@ -387,13 +254,18 @@ daemonConfigLoadOptions(struct daemonConfig *data,
const char *filename,
virConfPtr conf)
{
GET_CONF_UINT(conf, filename, listen_tcp);
GET_CONF_UINT(conf, filename, listen_tls);
GET_CONF_STR(conf, filename, tls_port);
GET_CONF_STR(conf, filename, tcp_port);
GET_CONF_STR(conf, filename, listen_addr);
if (virConfGetValueBool(conf, "listen_tcp", &data->listen_tcp) < 0)
goto error;
if (virConfGetValueBool(conf, "listen_tls", &data->listen_tls) < 0)
goto error;
if (virConfGetValueString(conf, "tls_port", &data->tls_port) < 0)
goto error;
if (virConfGetValueString(conf, "tcp_port", &data->tcp_port) < 0)
goto error;
if (virConfGetValueString(conf, "listen_addr", &data->listen_addr) < 0)
goto error;
if (remoteConfigGetAuth(conf, "auth_unix_rw", &data->auth_unix_rw, filename) < 0)
if (remoteConfigGetAuth(conf, filename, "auth_unix_rw", &data->auth_unix_rw) < 0)
goto error;
#if WITH_POLKIT
/* Change default perms to be wide-open if PolicyKit is enabled.
......@@ -405,78 +277,116 @@ daemonConfigLoadOptions(struct daemonConfig *data,
goto error;
}
#endif
if (remoteConfigGetAuth(conf, "auth_unix_ro", &data->auth_unix_ro, filename) < 0)
if (remoteConfigGetAuth(conf, filename, "auth_unix_ro", &data->auth_unix_ro) < 0)
goto error;
if (remoteConfigGetAuth(conf, "auth_tcp", &data->auth_tcp, filename) < 0)
if (remoteConfigGetAuth(conf, filename, "auth_tcp", &data->auth_tcp) < 0)
goto error;
if (remoteConfigGetAuth(conf, "auth_tls", &data->auth_tls, filename) < 0)
if (remoteConfigGetAuth(conf, filename, "auth_tls", &data->auth_tls) < 0)
goto error;
if (remoteConfigGetStringList(conf, "access_drivers",
&data->access_drivers, filename) < 0)
if (virConfGetValueStringList(conf, "access_drivers", false,
&data->access_drivers) < 0)
goto error;
GET_CONF_STR(conf, filename, unix_sock_group);
GET_CONF_STR(conf, filename, unix_sock_admin_perms);
GET_CONF_STR(conf, filename, unix_sock_ro_perms);
GET_CONF_STR(conf, filename, unix_sock_rw_perms);
if (virConfGetValueString(conf, "unix_sock_group", &data->unix_sock_group) < 0)
goto error;
if (virConfGetValueString(conf, "unix_sock_admin_perms", &data->unix_sock_admin_perms) < 0)
goto error;
if (virConfGetValueString(conf, "unix_sock_ro_perms", &data->unix_sock_ro_perms) < 0)
goto error;
if (virConfGetValueString(conf, "unix_sock_rw_perms", &data->unix_sock_rw_perms) < 0)
goto error;
GET_CONF_STR(conf, filename, unix_sock_dir);
if (virConfGetValueString(conf, "unix_sock_dir", &data->unix_sock_dir) < 0)
goto error;
GET_CONF_UINT(conf, filename, mdns_adv);
GET_CONF_STR(conf, filename, mdns_name);
if (virConfGetValueBool(conf, "mdns_adv", &data->mdns_adv) < 0)
goto error;
if (virConfGetValueString(conf, "mdns_name", &data->mdns_name) < 0)
goto error;
GET_CONF_UINT(conf, filename, tls_no_sanity_certificate);
GET_CONF_UINT(conf, filename, tls_no_verify_certificate);
if (virConfGetValueBool(conf, "tls_no_sanity_certificate", &data->tls_no_sanity_certificate) < 0)
goto error;
if (virConfGetValueBool(conf, "tls_no_verify_certificate", &data->tls_no_verify_certificate) < 0)
goto error;
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);
if (virConfGetValueString(conf, "key_file", &data->key_file) < 0)
goto error;
if (virConfGetValueString(conf, "cert_file", &data->cert_file) < 0)
goto error;
if (virConfGetValueString(conf, "ca_file", &data->ca_file) < 0)
goto error;
if (virConfGetValueString(conf, "crl_file", &data->crl_file) < 0)
goto error;
if (remoteConfigGetStringList(conf, "tls_allowed_dn_list",
&data->tls_allowed_dn_list, filename) < 0)
if (virConfGetValueStringList(conf, "tls_allowed_dn_list", false,
&data->tls_allowed_dn_list) < 0)
goto error;
if (remoteConfigGetStringList(conf, "sasl_allowed_username_list",
&data->sasl_allowed_username_list, filename) < 0)
if (virConfGetValueStringList(conf, "sasl_allowed_username_list", false,
&data->sasl_allowed_username_list) < 0)
goto error;
GET_CONF_STR(conf, filename, tls_priority);
if (virConfGetValueString(conf, "tls_priority", &data->tls_priority) < 0)
goto error;
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);
if (virConfGetValueUInt(conf, "min_workers", &data->min_workers) < 0)
goto error;
if (virConfGetValueUInt(conf, "max_workers", &data->max_workers) < 0)
goto error;
if (virConfGetValueUInt(conf, "max_clients", &data->max_clients) < 0)
goto error;
if (virConfGetValueUInt(conf, "max_queued_clients", &data->max_queued_clients) < 0)
goto error;
if (virConfGetValueUInt(conf, "max_anonymous_clients", &data->max_anonymous_clients) < 0)
goto error;
GET_CONF_UINT(conf, filename, prio_workers);
if (virConfGetValueUInt(conf, "prio_workers", &data->prio_workers) < 0)
goto error;
GET_CONF_INT(conf, filename, max_requests);
GET_CONF_UINT(conf, filename, max_client_requests);
if (virConfGetValueUInt(conf, "max_requests", &data->max_requests) < 0)
goto error;
if (virConfGetValueUInt(conf, "max_client_requests", &data->max_client_requests) < 0)
goto error;
GET_CONF_UINT(conf, filename, admin_min_workers);
GET_CONF_UINT(conf, filename, admin_max_workers);
GET_CONF_UINT(conf, filename, admin_max_clients);
GET_CONF_UINT(conf, filename, admin_max_queued_clients);
GET_CONF_UINT(conf, filename, admin_max_client_requests);
if (virConfGetValueUInt(conf, "admin_min_workers", &data->admin_min_workers) < 0)
goto error;
if (virConfGetValueUInt(conf, "admin_max_workers", &data->admin_max_workers) < 0)
goto error;
if (virConfGetValueUInt(conf, "admin_max_clients", &data->admin_max_clients) < 0)
goto error;
if (virConfGetValueUInt(conf, "admin_max_queued_clients", &data->admin_max_queued_clients) < 0)
goto error;
if (virConfGetValueUInt(conf, "admin_max_client_requests", &data->admin_max_client_requests) < 0)
goto error;
GET_CONF_UINT(conf, filename, audit_level);
GET_CONF_UINT(conf, filename, audit_logging);
if (virConfGetValueUInt(conf, "audit_level", &data->audit_level) < 0)
goto error;
if (virConfGetValueBool(conf, "audit_logging", &data->audit_logging) < 0)
goto error;
GET_CONF_STR(conf, filename, host_uuid);
GET_CONF_STR(conf, filename, host_uuid_source);
if (virConfGetValueString(conf, "host_uuid", &data->host_uuid) < 0)
goto error;
if (virConfGetValueString(conf, "host_uuid_source", &data->host_uuid_source) < 0)
goto error;
GET_CONF_UINT(conf, filename, log_level);
GET_CONF_STR(conf, filename, log_filters);
GET_CONF_STR(conf, filename, log_outputs);
if (virConfGetValueUInt(conf, "log_level", &data->log_level) < 0)
goto error;
if (virConfGetValueString(conf, "log_filters", &data->log_filters) < 0)
goto error;
if (virConfGetValueString(conf, "log_outputs", &data->log_outputs) < 0)
goto error;
GET_CONF_INT(conf, filename, keepalive_interval);
GET_CONF_UINT(conf, filename, keepalive_count);
if (virConfGetValueInt(conf, "keepalive_interval", &data->keepalive_interval) < 0)
goto error;
if (virConfGetValueUInt(conf, "keepalive_count", &data->keepalive_count) < 0)
goto error;
GET_CONF_INT(conf, filename, admin_keepalive_interval);
GET_CONF_UINT(conf, filename, admin_keepalive_count);
if (virConfGetValueInt(conf, "admin_keepalive_interval", &data->admin_keepalive_interval) < 0)
goto error;
if (virConfGetValueUInt(conf, "admin_keepalive_count", &data->admin_keepalive_count) < 0)
goto error;
return 0;
......
......@@ -30,8 +30,8 @@ struct daemonConfig {
char *host_uuid;
char *host_uuid_source;
int listen_tls;
int listen_tcp;
bool listen_tls;
bool listen_tcp;
char *listen_addr;
char *tls_port;
char *tcp_port;
......@@ -49,11 +49,11 @@ struct daemonConfig {
char **access_drivers;
int mdns_adv;
bool mdns_adv;
char *mdns_name;
int tls_no_verify_certificate;
int tls_no_sanity_certificate;
bool tls_no_verify_certificate;
bool tls_no_sanity_certificate;
char **tls_allowed_dn_list;
char **sasl_allowed_username_list;
char *tls_priority;
......@@ -63,32 +63,32 @@ struct daemonConfig {
char *ca_file;
char *crl_file;
int min_workers;
int max_workers;
int max_clients;
int max_queued_clients;
int max_anonymous_clients;
unsigned int min_workers;
unsigned int max_workers;
unsigned int max_clients;
unsigned int max_queued_clients;
unsigned int max_anonymous_clients;
int prio_workers;
unsigned int prio_workers;
int max_requests;
int max_client_requests;
unsigned int max_requests;
unsigned int max_client_requests;
int log_level;
unsigned int log_level;
char *log_filters;
char *log_outputs;
int audit_level;
int audit_logging;
unsigned int audit_level;
bool audit_logging;
int keepalive_interval;
unsigned int keepalive_count;
int admin_min_workers;
int admin_max_workers;
int admin_max_clients;
int admin_max_queued_clients;
int admin_max_client_requests;
unsigned int admin_min_workers;
unsigned int admin_max_workers;
unsigned int admin_max_clients;
unsigned int admin_max_queued_clients;
unsigned int admin_max_client_requests;
int admin_keepalive_interval;
unsigned int admin_keepalive_count;
......
......@@ -378,8 +378,7 @@ if WITH_LIBVIRTD
test_scripts += $(libvirtd_test_scripts)
test_programs += \
eventtest \
libvirtdconftest
eventtest
else ! WITH_LIBVIRTD
EXTRA_DIST += $(libvirtd_test_scripts)
endif ! WITH_LIBVIRTD
......@@ -956,15 +955,6 @@ domaincapstest_SOURCES += testutilsxen.c testutilsxen.h
domaincapstest_LDADD += ../src/libvirt_driver_libxl_impl.la
endif WITH_LIBXL
if WITH_LIBVIRTD
libvirtdconftest_SOURCES = \
libvirtdconftest.c testutils.h testutils.c \
$(NULL)
libvirtdconftest_LDADD = ../daemon/libvirtd_conf.la $(LDADDS)
else ! WITH_LIBVIRTD
EXTRA_DIST += libvirtdconftest.c
endif ! WITH_LIBVIRTD
virnetmessagetest_SOURCES = \
virnetmessagetest.c testutils.h testutils.c
virnetmessagetest_CFLAGS = $(XDR_CFLAGS) $(AM_CFLAGS)
......
/*
* Copyright (C) 2012-2014 Red Hat, Inc.
*
* 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, see
* <http://www.gnu.org/licenses/>.
*
* Author: Daniel P. Berrange <berrange@redhat.com>
*/
#include <config.h>
#include <stdlib.h>
#include "testutils.h"
#include "daemon/libvirtd-config.h"
#include "virutil.h"
#include "c-ctype.h"
#include "virerror.h"
#include "virfile.h"
#include "virlog.h"
#include "virconf.h"
#include "virstring.h"
#define VIR_FROM_THIS VIR_FROM_NONE
VIR_LOG_INIT("tests.libvirtdconftest");
struct testCorruptData {
size_t *params;
const char *filedata;
const char *filename;
size_t paramnum;
};
static char *
munge_param(const char *datain,
size_t *params,
size_t paramnum,
int *type)
{
char *dataout;
const char *sol;
const char *eol;
const char *eq;
const char *tmp;
size_t dataoutlen;
const char *replace = NULL;
sol = datain + params[paramnum];
eq = strchr(sol, '=');
eol = strchr(sol, '\n');
for (tmp = eq + 1; tmp < eol && !replace; tmp++) {
if (c_isspace(*tmp))
continue;
if (c_isdigit(*tmp)) {
*type = VIR_CONF_ULONG;
replace = "\"foo\"";
} else if (*tmp == '[') {
*type = VIR_CONF_LIST;
replace = "666";
} else {
*type = VIR_CONF_STRING;
replace = "666";
}
}
dataoutlen = (eq - datain) + 1 +
strlen(replace) +
strlen(eol) + 1;
if (VIR_ALLOC_N(dataout, dataoutlen) < 0)
return NULL;
memcpy(dataout, datain, (eq - datain) + 1);
memcpy(dataout + (eq - datain) + 1,
replace, strlen(replace));
memcpy(dataout + (eq - datain) + 1 + strlen(replace),
eol, strlen(eol) + 1);
return dataout;
}
static int
testCorrupt(const void *opaque)
{
const struct testCorruptData *data = opaque;
struct daemonConfig *conf = daemonConfigNew(false);
int ret = 0;
int type = VIR_CONF_NONE;
char *newdata = munge_param(data->filedata,
data->params,
data->paramnum,
&type);
const char *err = NULL;
if (!newdata)
return -1;
//VIR_DEBUG("New config [%s]", newdata);
if (daemonConfigLoadData(conf, data->filename, newdata) != -1) {
VIR_DEBUG("Did not see a failure");
ret = -1;
goto cleanup;
}
err = virGetLastErrorMessage();
if (!err) {
VIR_DEBUG("No error or message %p", err);
ret = -1;
goto cleanup;
}
#if !WITH_SASL
if (strstr(err, "unsupported auth sasl")) {
VIR_DEBUG("sasl unsupported, skipping this config");
goto cleanup;
}
#endif
switch (type) {
case VIR_CONF_ULONG:
if (!strstr(err, "invalid type: got string; expected unsigned long") &&
!strstr(err, "invalid type: got string; expected long")) {
VIR_DEBUG("Wrong error for long: '%s'",
err);
ret = -1;
}
break;
case VIR_CONF_STRING:
if (!strstr(err, "invalid type: got unsigned long; expected string")) {
VIR_DEBUG("Wrong error for string: '%s'",
err);
ret = -1;
}
break;
case VIR_CONF_LIST:
if (!strstr(err, "must be a string or list of strings")) {
VIR_DEBUG("Wrong error for list: '%s'",
err);
ret = -1;
}
break;
}
cleanup:
VIR_FREE(newdata);
daemonConfigFree(conf);
return ret;
}
static int
uncomment_all_params(char *data,
size_t **ret)
{
size_t count = 0;
char *tmp;
size_t *params = 0;
tmp = data;
while (tmp && *tmp) {
tmp = strchr(tmp, '\n');
if (!tmp)
break;
tmp++;
/* Uncomment any lines starting #some_var */
if (*tmp == '#' &&
c_isalpha(*(tmp + 1))) {
if (VIR_EXPAND_N(params, count, 1) < 0) {
VIR_FREE(params);
return -1;
}
*tmp = ' ';
params[count-1] = (tmp + 1) - data;
}
}
if (VIR_EXPAND_N(params, count, 1) < 0) {
VIR_FREE(params);
return -1;
}
params[count-1] = 0;
*ret = params;
return count;
}
static int
mymain(void)
{
int ret = 0;
char *filedata = NULL;
char *filename = NULL;
size_t i;
size_t *params = NULL;
if (virAsprintf(&filename, "%s/../daemon/libvirtd.conf",
abs_srcdir) < 0) {
perror("Format filename");
return EXIT_FAILURE;
}
if (virFileReadAll(filename, 1024*1024, &filedata) < 0) {
const char *err = virGetLastErrorMessage();
fprintf(stderr, "Cannot load %s for testing: %s", filename, err);
ret = -1;
goto cleanup;
}
if (uncomment_all_params(filedata, &params) < 0) {
perror("Find params");
ret = -1;
goto cleanup;
}
VIR_DEBUG("Initial config [%s]", filedata);
for (i = 0; params[i] != 0; i++) {
const struct testCorruptData data = { params, filedata, filename, i };
/* Skip now ignored config param */
if (STRPREFIX(filedata + params[i], "log_buffer_size") ||
STRPREFIX(filedata + params[i], "keepalive_required") ||
STRPREFIX(filedata + params[i], "admin_keepalive_required"))
continue;
if (virTestRun("Test corruption", testCorrupt, &data) < 0)
ret = -1;
}
cleanup:
VIR_FREE(filename);
VIR_FREE(filedata);
VIR_FREE(params);
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}
VIRT_TEST_MAIN(mymain)
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册