"Daniel P. Berrange" <berrange(a)redhat.com> wrote:
On Wed, Nov 28, 2007 at 02:18:22PM +0100, Jim Meyering wrote:
> I spotted a few unchecked heap allocations (strdup, malloc, calloc)
> in qemud.c and have fixed it so such failure evokes a proper diagnostic
> rather than e.g., a segfault.
Yep, good stuff.
> I've also arranged to free some of the memory upon failure,
> but not all (see comments for why).
>
> In spite of those additions, this patch factors out enough
> duplication that the net change is to remove a few lines from the
> file. Although in general I prefer to factor things out into
> separate functions, in this case, it seemed better to use macros.
I really don't like the macros, particularly when the macro definitions
are inline to the function. I'd prefer to see these helpers as separate
functions. The compiler is perfectly able to decide whether to inline
the code or not & it makes it more friendly to edit & read when it is
using separate functions.
I've rewritten to use fewer macros.
In the process, I did a little testing, and will
add an automated test to give this code some coverage
in a separate patch.
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.
* qemud/libvirtd.conf: Add '=' signs to correct invalid syntax
in commented out config lines. Distinguish those lines by
having no space between '#' and the following character.
---
qemud/libvirtd.conf | 50 ++++----
qemud/qemud.c | 378 ++++++++++++++++++++++++++++++---------------------
src/conf.h | 26 ++++-
3 files changed, 273 insertions(+), 181 deletions(-)
diff --git a/qemud/libvirtd.conf b/qemud/libvirtd.conf
index 51168b8..b427e14 100644
--- a/qemud/libvirtd.conf
+++ b/qemud/libvirtd.conf
@@ -11,7 +11,7 @@
# using this capability.
#
# This is enabled by default, uncomment this to disable it
-# listen_tls = 0
+#listen_tls = 0
# Listen for unencrypted TCP connections on the public TCP/IP port.
# NB, must pass the --listen flag to the libvirtd process for this to
@@ -20,19 +20,19 @@
# NB, this is insecure. Do not use except for development.
#
# This is disabled by default, uncomment this to enable it.
-# listen_tcp = 1
+#listen_tcp = 1
# Override the port for accepting secure TLS connections
# This can be a port number, or service name
#
-# tls_port = "16514"
+#tls_port = "16514"
# Override the port for accepting insecure TCP connections
# This can be a port number, or service name
-#
-# tcp_port = "16509"
+#
+#tcp_port = "16509"
@@ -42,38 +42,38 @@
# stopping the Avahi daemon
#
# This is enabled by default, uncomment this to disable it
-# mdns_adv = 0
+#mdns_adv = 0
# Override the default mDNS advertizement name. This must be
# unique on the immediate broadcast network.
-#
+#
# The default is "Virtualization Host HOSTNAME", where HOSTNAME
# is subsituted for the short hostname of the machine (without domain)
#
-# mdns_name "Virtualization Host Joe Demo"
+#mdns_name = "Virtualization Host Joe Demo"
# Set the UNIX domain socket group ownership. This can be used to
# allow a 'trusted' set of users access to management capabilities
# without becoming root.
-#
-# This is restricted to 'root' by default.
-# unix_sock_group "libvirt"
+#
+# This is restricted to 'root' by default.
+#unix_sock_group = "libvirt"
# Set the UNIX socket permissions for the R/O socket. This is used
# for monitoring VM status only
#
# Default allows any user. If setting group ownership may want to
# restrict this to:
-# unix_sock_ro_perms "0777"
+#unix_sock_ro_perms = "0777"
# Set the UNIX socket permissions for the R/W socket. This is used
# for full management of VMs
#
# Default allows only root. If setting group ownership may want to
# relax this to:
-# unix_sock_rw_perms "octal-perms" "0770"
+#unix_sock_rw_perms = "0770"
@@ -85,7 +85,7 @@
#
# Default is to always verify. Uncommenting this will disable
# verification - make sure an IP whitelist is set
-# tls_no_verify_certificate 1
+#tls_no_verify_certificate = 1
# Flag to disable verification of client IP address
#
@@ -94,27 +94,27 @@
# it is easy to spoof source IP.
#
# Uncommenting this will disable verification
-# tls_no_verify_address 1
+#tls_no_verify_address = 1
# Override the default server key file path
#
-# key_file "/etc/pki/libvirt/private/serverkey.pem"
+#key_file = "/etc/pki/libvirt/private/serverkey.pem"
# Override the default server certificate file path
#
-# cert_file "/etc/pki/libvirt/servercert.pem"
+#cert_file = "/etc/pki/libvirt/servercert.pem"
# Override the default CA certificate path
#
-# ca_file "/etc/pki/CA/cacert.pem"
+#ca_file = "/etc/pki/CA/cacert.pem"
# Specify a certificate revocation list.
-#
+#
# Defaults to not using a CRL, uncomment to enable it
-# crl_file "/etc/pki/CA/crl.pem"
+#crl_file = "/etc/pki/CA/crl.pem"
# A whitelist of allowed x509 Distinguished Names
-# This list may contain wildcards such as
+# This list may contain wildcards such as
#
# "C=GB,ST=London,L=London,O=Red Hat,CN=*"
#
@@ -124,18 +124,16 @@
# entirely rather than using empty list to disable these checks
#
# By default, no DN's are checked
-# tls_allowed_dn_list ["DN1", "DN2"]
+#tls_allowed_dn_list = ["DN1", "DN2"]
# A whitelist of allowed client IP addresses
#
-# This list may contain wildcards such as 192.168.* See the POSIX fnmatch
+# This list may contain wildcards such as 192.168.* See the POSIX fnmatch
# function for the format of the wildcards.
#
# NB If this is an empty list, no client can connect, so comment out
# entirely rather than using empty list to disable these checks
#
# By default, no IP's are checked. This can be IPv4 or IPv6 addresses
-# tls_allowed_ip_list ["ip1", "ip2", "ip3"]
-
-
+#tls_allowed_ip_list = ["ip1", "ip2", "ip3"]
diff --git a/qemud/qemud.c b/qemud/qemud.c
index 5f76a26..9904e4a 100644
--- a/qemud/qemud.c
+++ b/qemud/qemud.c
@@ -70,27 +70,27 @@ static int ipsock = 0; /* -l Listen for TCP/IP */
/* Defaults for configuration file elements */
static int listen_tls = 1;
static int listen_tcp = 0;
-static const char *tls_port = LIBVIRTD_TLS_PORT;
-static const char *tcp_port = LIBVIRTD_TCP_PORT;
+static char *tls_port = (char *) LIBVIRTD_TLS_PORT;
+static char *tcp_port = (char *) LIBVIRTD_TCP_PORT;
static gid_t unix_sock_gid = 0; /* Only root by default */
-static int unix_sock_rw_perms = 0700; /* Allow user only */
-static int unix_sock_ro_perms = 0777; /* Allow world */
+static int unix_sock_rw_mask = 0700; /* Allow user only */
+static int unix_sock_ro_mask = 0777; /* Allow world */
#ifdef HAVE_AVAHI
static int mdns_adv = 1;
-static const char *mdns_name = NULL;
+static char *mdns_name = NULL;
#endif
static int tls_no_verify_certificate = 0;
static int tls_no_verify_address = 0;
-static const char **tls_allowed_ip_list = 0;
-static const char **tls_allowed_dn_list = 0;
+static char **tls_allowed_ip_list = NULL;
+static char **tls_allowed_dn_list = NULL;
-static const char *key_file = LIBVIRT_SERVERKEY;
-static const char *cert_file = LIBVIRT_SERVERCERT;
-static const char *ca_file = LIBVIRT_CACERT;
-static const char *crl_file = "";
+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 *) "";
static gnutls_certificate_credentials_t x509_cred;
static gnutls_dh_params_t dh_params;
@@ -407,7 +407,7 @@ static int qemudGoDaemon(void) {
status != 0) {
return -1;
}
-
+
return pid;
}
}
@@ -482,7 +482,7 @@ static int qemudListenUnix(struct qemud_server *server,
oldgrp = getgid();
- oldmask = umask(readonly ? ~unix_sock_ro_perms : ~unix_sock_rw_perms);
+ oldmask = umask(readonly ? ~unix_sock_ro_mask : ~unix_sock_rw_mask);
if (getuid() == 0)
setgid(unix_sock_gid);
@@ -649,7 +649,7 @@ static int qemudInitPaths(struct qemud_server *server,
char *base = 0;
uid_t uid = geteuid();
-
+
if (!uid) {
if (snprintf (sockname, maxlen, "%s/run/libvirt/libvirt-sock",
LOCAL_STATE_DIR) >= maxlen)
@@ -764,7 +764,7 @@ static struct qemud_server *qemudInitialize(int sigread) {
group = libvirtd_mdns_add_group(server->mdns, mdns_name);
}
- /*
+ /*
* 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
@@ -777,7 +777,7 @@ static struct qemud_server *qemudInitialize(int sigread) {
}
sock = sock->next;
}
-
+
/*
* Add the primary entry - we choose SSH because its most likely to always
* be available
@@ -840,7 +840,7 @@ remoteCheckDN (gnutls_x509_crt_t cert)
{
char name[256];
size_t namesize = sizeof name;
- const char **wildcards;
+ char **wildcards;
int err;
err = gnutls_x509_crt_get_dn (cert, name, &namesize);
@@ -928,13 +928,13 @@ remoteCheckCertificate (gnutls_session_t session)
gnutls_x509_crt_deinit (cert);
return -1;
}
-
+
if (gnutls_x509_crt_get_expiration_time (cert) < now) {
qemudLog (QEMUD_ERR, "remoteCheckCertificate: the client certificate has
expired");
gnutls_x509_crt_deinit (cert);
return -1;
}
-
+
if (gnutls_x509_crt_get_activation_time (cert) > now) {
qemudLog (QEMUD_ERR, "remoteCheckCertificate: the client certificate is
not yet activated");
gnutls_x509_crt_deinit (cert);
@@ -959,7 +959,7 @@ static int
remoteCheckAccess (struct qemud_client *client)
{
char addr[NI_MAXHOST];
- const char **wildcards;
+ char **wildcards;
int found, err;
/* Verify client certificate. */
@@ -1044,6 +1044,8 @@ static int qemudDispatchServer(struct qemud_server *server, struct
qemud_socket
}
client = calloc(1, sizeof(struct qemud_client));
+ if (client == NULL)
+ goto cleanup;
client->magic = QEMUD_CLIENT_MAGIC;
client->fd = fd;
client->readonly = sock->readonly;
@@ -1505,6 +1507,131 @@ static void qemudCleanup(struct qemud_server *server) {
free(server);
}
+/* 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:
+ list = malloc (2 * sizeof (*list));
+ if (list == NULL) {
+ qemudLog (QEMUD_ERR,
+ "failed to allocate memory for %s config list", key);
+ return -1;
+ }
+ list[0] = strdup (p->str);
+ list[1] = NULL;
+ if (list[0] == NULL) {
+ qemudLog (QEMUD_ERR,
+ "failed to allocate memory for %s config list value",
+ key);
+ free (list);
+ return -1;
+ }
+ break;
+
+ case VIR_CONF_LIST: {
+ int i, len = 0;
+ virConfValuePtr pp;
+ for (pp = p->list; pp; pp = pp->next)
+ len++;
+ list = calloc (1+len, sizeof (*list));
+ if (list == NULL) {
+ qemudLog (QEMUD_ERR,
+ "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) {
+ qemudLog (QEMUD_ERR, "remoteReadConfigFile: %s: %s:"
+ " must be a string or list of strings\n",
+ filename, key);
+ free (list);
+ return -1;
+ }
+ list[i] = strdup (pp->str);
+ if (list[i] == NULL) {
+ int j;
+ for (j = 0 ; j < i ; j++)
+ free (list[j]);
+ free (list);
+ qemudLog (QEMUD_ERR, "failed to allocate memory"
+ " for %s config list value", key);
+ return -1;
+ }
+
+ }
+ list[i] = NULL;
+ break;
+ }
+
+ default:
+ qemudLog (QEMUD_ERR, "remoteReadConfigFile: %s: %s:"
+ " must be a string or list of strings\n",
+ 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) {
+ qemudLog (QEMUD_ERR,
+ "remoteReadConfigFile: %s: %s: invalid type:"
+ " got %s; expected %s\n", filename, key,
+ 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) { \
+ qemudLog (QEMUD_ERR, "remoteReadConfigFile: %s\n", \
+ strerror (errno)); \
+ 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)
+
/* Read the config file if it exists.
* Only used in the remote case, hence the name.
*/
@@ -1513,6 +1640,12 @@ remoteReadConfigFile (const char *filename)
{
virConfPtr conf;
+ /* 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;
+
/* Just check the file is readable before opening it, otherwise
* libvirt emits an error.
*/
@@ -1521,166 +1654,103 @@ remoteReadConfigFile (const char *filename)
conf = virConfReadFile (filename);
if (!conf) return 0;
- virConfValuePtr p;
-
-#define CHECK_TYPE(name,typ) if (p && p->type != (typ)) { \
- qemudLog (QEMUD_ERR, \
- "remoteReadConfigFile: %s: %s: expected type " #typ
"\n", \
- filename, (name)); \
- return -1; \
- }
-
- p = virConfGetValue (conf, "listen_tls");
- CHECK_TYPE ("listen_tls", VIR_CONF_LONG);
- listen_tls = p ? p->l : listen_tls;
-
- p = virConfGetValue (conf, "listen_tcp");
- CHECK_TYPE ("listen_tcp", VIR_CONF_LONG);
- listen_tcp = p ? p->l : listen_tcp;
-
- p = virConfGetValue (conf, "tls_port");
- CHECK_TYPE ("tls_port", VIR_CONF_STRING);
- tls_port = p ? strdup (p->str) : tls_port;
-
- p = virConfGetValue (conf, "tcp_port");
- CHECK_TYPE ("tcp_port", VIR_CONF_STRING);
- tcp_port = p ? strdup (p->str) : tcp_port;
+ GET_CONF_STR (conf, filename, tls_port);
+ GET_CONF_STR (conf, filename, tcp_port);
- p = virConfGetValue (conf, "unix_sock_group");
- CHECK_TYPE ("unix_sock_group", VIR_CONF_STRING);
- if (p && p->str) {
+ GET_CONF_STR (conf, filename, unix_sock_group);
+ if (unix_sock_group) {
if (getuid() != 0) {
qemudLog (QEMUD_WARN, "Cannot set group when not running as
root");
} else {
- struct group *grp = getgrnam(p->str);
+ struct group *grp = getgrnam(unix_sock_group);
if (!grp) {
- qemudLog (QEMUD_ERR, "Failed to lookup group '%s'",
p->str);
- return -1;
+ qemudLog (QEMUD_ERR, "Failed to lookup group '%s'",
+ unix_sock_group);
+ goto free_and_fail;
}
unix_sock_gid = grp->gr_gid;
}
+ free (unix_sock_group);
+ unix_sock_group = NULL;
}
- p = virConfGetValue (conf, "unix_sock_ro_perms");
- CHECK_TYPE ("unix_sock_ro_perms", VIR_CONF_STRING);
- if (p && p->str) {
- if (xstrtol_i(p->str, NULL, 8, &unix_sock_ro_perms) != 0) {
- qemudLog (QEMUD_ERR, "Failed to parse mode '%s'",
p->str);
- return -1;
+ GET_CONF_STR (conf, filename, unix_sock_ro_perms);
+ if (unix_sock_ro_perms) {
+ if (xstrtol_i (unix_sock_ro_perms, NULL, 8, &unix_sock_ro_mask) != 0) {
+ qemudLog (QEMUD_ERR, "Failed to parse mode '%s'",
+ unix_sock_ro_perms);
+ goto free_and_fail;
}
+ free (unix_sock_ro_perms);
+ unix_sock_ro_perms = NULL;
}
- p = virConfGetValue (conf, "unix_sock_rw_perms");
- CHECK_TYPE ("unix_sock_rw_perms", VIR_CONF_STRING);
- if (p && p->str) {
- if (xstrtol_i(p->str, NULL, 8, &unix_sock_rw_perms) != 0) {
- qemudLog (QEMUD_ERR, "Failed to parse mode '%s'",
p->str);
- return -1;
+ GET_CONF_STR (conf, filename, unix_sock_rw_perms);
+ if (unix_sock_rw_perms) {
+ if (xstrtol_i (unix_sock_rw_perms, NULL, 8, &unix_sock_rw_mask) != 0) {
+ qemudLog (QEMUD_ERR, "Failed to parse mode '%s'",
+ unix_sock_rw_perms);
+ goto free_and_fail;
}
+ free (unix_sock_rw_perms);
+ unix_sock_rw_perms = NULL;
}
#ifdef HAVE_AVAHI
- p = virConfGetValue (conf, "mdns_adv");
- CHECK_TYPE ("mdns_adv", VIR_CONF_LONG);
- mdns_adv = p ? p->l : mdns_adv;
-
- p = virConfGetValue (conf, "mdns_name");
- CHECK_TYPE ("mdns_name", VIR_CONF_STRING);
- mdns_name = p ? strdup (p->str) : NULL;
+ GET_CONF_INT (conf, filename, mdns_adv);
+ GET_CONF_STR (conf, filename, mdns_name);
#endif
- p = virConfGetValue (conf, "tls_no_verify_certificate");
- CHECK_TYPE ("tls_no_verify_certificate", VIR_CONF_LONG);
- tls_no_verify_certificate = p ? p->l : tls_no_verify_certificate;
-
- p = virConfGetValue (conf, "tls_no_verify_address");
- CHECK_TYPE ("tls_no_verify_address", VIR_CONF_LONG);
- tls_no_verify_address = p ? p->l : tls_no_verify_address;
-
- p = virConfGetValue (conf, "key_file");
- CHECK_TYPE ("key_file", VIR_CONF_STRING);
- key_file = p ? strdup (p->str) : key_file;
-
- p = virConfGetValue (conf, "cert_file");
- CHECK_TYPE ("cert_file", VIR_CONF_STRING);
- cert_file = p ? strdup (p->str) : cert_file;
-
- p = virConfGetValue (conf, "ca_file");
- CHECK_TYPE ("ca_file", VIR_CONF_STRING);
- ca_file = p ? strdup (p->str) : ca_file;
-
- p = virConfGetValue (conf, "crl_file");
- CHECK_TYPE ("crl_file", VIR_CONF_STRING);
- crl_file = p ? strdup (p->str) : crl_file;
-
- p = virConfGetValue (conf, "tls_allowed_dn_list");
- if (p) {
- switch (p->type) {
- case VIR_CONF_STRING:
- tls_allowed_dn_list = malloc (2 * sizeof (char *));
- tls_allowed_dn_list[0] = strdup (p->str);
- tls_allowed_dn_list[1] = 0;
- break;
+ GET_CONF_INT (conf, filename, tls_no_verify_certificate);
+ GET_CONF_INT (conf, filename, tls_no_verify_address);
- case VIR_CONF_LIST: {
- int i, len = 0;
- virConfValuePtr pp;
- for (pp = p->list; pp; pp = p->next)
- len++;
- tls_allowed_dn_list =
- malloc ((1+len) * sizeof (char *));
- for (i = 0, pp = p->list; pp; ++i, pp = p->next) {
- if (pp->type != VIR_CONF_STRING) {
- qemudLog (QEMUD_ERR, "remoteReadConfigFile: %s:
tls_allowed_dn_list: should be a string or list of strings\n", filename);
- return -1;
- }
- tls_allowed_dn_list[i] = strdup (pp->str);
- }
- tls_allowed_dn_list[i] = 0;
- break;
- }
+ 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);
- default:
- qemudLog (QEMUD_ERR, "remoteReadConfigFile: %s: tls_allowed_dn_list:
should be a string or list of strings\n", filename);
- return -1;
- }
- }
+ if (remoteConfigGetStringList (conf, "tls_allowed_dn_list",
+ &tls_allowed_dn_list, filename) < 0)
+ goto free_and_fail;
- p = virConfGetValue (conf, "tls_allowed_ip_list");
- if (p) {
- switch (p->type) {
- case VIR_CONF_STRING:
- tls_allowed_ip_list = malloc (2 * sizeof (char *));
- tls_allowed_ip_list[0] = strdup (p->str);
- tls_allowed_ip_list[1] = 0;
- break;
+ if (remoteConfigGetStringList (conf, "tls_allowed_ip_list",
+ &tls_allowed_ip_list, filename) < 0)
+ goto free_and_fail;
- case VIR_CONF_LIST: {
- int i, len = 0;
- virConfValuePtr pp;
- for (pp = p->list; pp; pp = p->next)
- len++;
- tls_allowed_ip_list =
- malloc ((1+len) * sizeof (char *));
- for (i = 0, pp = p->list; pp; ++i, pp = p->next) {
- if (pp->type != VIR_CONF_STRING) {
- qemudLog (QEMUD_ERR, "remoteReadConfigFile: %s:
tls_allowed_ip_list: should be a string or list of strings\n", filename);
- return -1;
- }
- tls_allowed_ip_list[i] = strdup (pp->str);
- }
- tls_allowed_ip_list[i] = 0;
- break;
- }
+ virConfFree (conf);
+ return 0;
- default:
- qemudLog (QEMUD_ERR, "remoteReadConfigFile: %s: tls_allowed_ip_list:
should be a string or list of strings\n", filename);
- return -1;
- }
+ 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);
+
+ /* Don't bother trying to free 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
+ 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;
+ }
+
+ if (tls_allowed_ip_list) {
+ int i;
+ for (i = 0; tls_allowed_ip_list[i]; i++)
+ free (tls_allowed_ip_list[i]);
+ free (tls_allowed_ip_list);
+ tls_allowed_ip_list = NULL;
}
- virConfFree (conf);
- return 0;
+ return -1;
}
/* Print command-line usage. */
diff --git a/src/conf.h b/src/conf.h
index 7a7ad25..53c9456 100644
--- a/src/conf.h
+++ b/src/conf.h
@@ -1,7 +1,7 @@
/**
* conf.h: parser for a subset of the Python encoded Xen configuration files
*
- * Copyright (C) 2006 Red Hat, Inc.
+ * Copyright (C) 2006, 2007 Red Hat, Inc.
*
* See COPYING.LIB for the License of this software
*
@@ -28,6 +28,21 @@ typedef enum {
VIR_CONF_LIST = 3 /* a list */
} virConfType;
+static inline const char *
+virConfTypeName (virConfType t)
+{
+ switch (t) {
+ case VIR_CONF_LONG:
+ return "long";
+ case VIR_CONF_STRING:
+ return "string";
+ case VIR_CONF_LIST:
+ return "list";
+ default:
+ return "*unexpected*";
+ }
+}
+
/**
* virConfValue:
* a value from the configuration file
@@ -80,3 +95,12 @@ int __virConfWriteMem (char *memory,
}
#endif
#endif /* __VIR_CONF_H__ */
+
+/*
+ * Local variables:
+ * indent-tabs-mode: nil
+ * c-indent-level: 4
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
--
1.5.3.6.961.gecf4