[libvirt] [PATCH v5 4/5] Network: Add additional hosts internal infrastructure
Laine Stump
laine at laine.org
Thu Jun 23 05:44:22 UTC 2011
On 06/14/2011 09:02 AM, Michal Novotny wrote:
> Signed-off-by: Michal Novotny<minovotn at redhat.com>
> ---
> docs/formatnetwork.html.in | 14 ++
> src/libvirt_private.syms | 1 +
> src/network/bridge_driver.c | 3 +
> src/util/dnsmasq.c | 285 ++++++++++++++++++++++++++++++++++++++++---
> src/util/dnsmasq.h | 22 +++-
> 5 files changed, 305 insertions(+), 20 deletions(-)
>
> diff --git a/docs/formatnetwork.html.in b/docs/formatnetwork.html.in
> index 62e1e08..a036545 100644
> --- a/docs/formatnetwork.html.in
> +++ b/docs/formatnetwork.html.in
> @@ -218,6 +218,20 @@
> element is used. The BOOTP options currently have to be the same
> for all address ranges and statically assigned addresses.<span
> class="since">Since 0.7.1 (<code>server</code> since 0.7.3).</span>
> +</dd>
> +<dt><code>host</code></dt>
> +<dd>The<code>host</code> element is the definition of DNS hosts to be passed
> + to the DNS service. The IP address is identified by the<code>ip</code> attribute
> + and the names for the IP addresses are identified in the<code>hostname</code>
> + subelements of the<code>host</code> element.
> +<span class="since">Since 0.9.1</span>
> +</dd>
> +<dt><code>host</code></dt>
> +<dd>The<code>host</code> element is the definition of DNS hosts to be passed
> + to the DNS service. The IP address is identified by the<code>ip</code> attribute
> + and the names for the IP addresses are identified in the<code>hostname</code>
> + subelements of the<code>host</code> element.
> +<span class="since">Since 0.9.1</span>
> </dd>
> </dl>
>
> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> index 737cd31..71ef9cc 100644
> --- a/src/libvirt_private.syms
> +++ b/src/libvirt_private.syms
> @@ -194,6 +194,7 @@ virUnrefStream;
>
> # dnsmasq.h
> dnsmasqAddDhcpHost;
> +dnsmasqAddHost;
> dnsmasqContextFree;
> dnsmasqContextNew;
> dnsmasqDelete;
> diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
> index 10bb928..f55f759 100644
> --- a/src/network/bridge_driver.c
> +++ b/src/network/bridge_driver.c
> @@ -607,6 +607,9 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network,
> if (dctx->hostsfile->nhosts)
> virCommandAddArgPair(cmd, "--dhcp-hostsfile",
> dctx->hostsfile->path);
> + if (dctx->addnhostsfile->nhosts)
> + virCommandAddArgPair(cmd, "--addn-hosts",
> + dctx->addnhostsfile->path);
>
> dnsmasqContextFree(dctx);
> }
> diff --git a/src/util/dnsmasq.c b/src/util/dnsmasq.c
> index 2ba9355..04a912a 100644
> --- a/src/util/dnsmasq.c
> +++ b/src/util/dnsmasq.c
> @@ -48,6 +48,7 @@
>
> #define VIR_FROM_THIS VIR_FROM_NETWORK
> #define DNSMASQ_HOSTSFILE_SUFFIX "hostsfile"
> +#define DNSMASQ_ADDNHOSTSFILE_SUFFIX "addnhosts"
>
> static void
> dhcphostFree(dnsmasqDhcpHost *host)
> @@ -56,6 +57,235 @@ dhcphostFree(dnsmasqDhcpHost *host)
> }
>
> static void
> +addnhostFree(dnsmasqAddnHost *host)
> +{
> + int i;
> +
> + for (i = 0; i< host->nhostnames; i++)
> + VIR_FREE(host->hostnames[i]);
> + VIR_FREE(host->hostnames);
> + VIR_FREE(host->ip);
> +}
> +
> +static void
> +addnhostsFree(dnsmasqAddnHostsfile *addnhostsfile)
> +{
> + unsigned int i;
> +
> + if (addnhostsfile->hosts) {
> + for (i = 0; i< addnhostsfile->nhosts; i++)
> + addnhostFree(&addnhostsfile->hosts[i]);
> +
> + VIR_FREE(addnhostsfile->hosts);
> +
> + addnhostsfile->nhosts = 0;
> + }
> +
> + VIR_FREE(addnhostsfile->path);
> +
> + VIR_FREE(addnhostsfile);
> +}
> +
> +static int
> +addnhostsAdd(dnsmasqAddnHostsfile *addnhostsfile,
> + virSocketAddr *ip,
> + const char *name)
> +{
> + char *ipstr = NULL;
> + int idx = -1;
> + int i;
> +
> + if (!(ipstr = virSocketFormatAddr(ip)))
> + return -1;
> +
> + for (i = 0; i< addnhostsfile->nhosts; i++) {
> + if (STREQ((const char *)addnhostsfile->hosts[i].ip, (const char *)ipstr)) {
> + idx = i;
> + break;
> + }
> + }
> +
> + if (idx< 0) {
> + if (VIR_REALLOC_N(addnhostsfile->hosts, addnhostsfile->nhosts + 1)< 0)
> + goto alloc_error;
> +
> + idx = addnhostsfile->nhosts;
> + if (VIR_ALLOC(addnhostsfile->hosts[idx].hostnames)< 0)
> + goto alloc_error;
> +
> + if (virAsprintf(&addnhostsfile->hosts[idx].ip, "%s", ipstr)< 0)
> + goto alloc_error;
> +
> + addnhostsfile->hosts[idx].nhostnames = 0;
> + addnhostsfile->nhosts++;
> + }
> +
> + if (VIR_REALLOC_N(addnhostsfile->hosts[idx].hostnames, addnhostsfile->hosts[idx].nhostnames + 1)< 0)
> + goto alloc_error;
> +
> + if (virAsprintf(&addnhostsfile->hosts[idx].hostnames[addnhostsfile->hosts[idx].nhostnames], "%s", name)< 0)
> + goto alloc_error;
> +
> + VIR_FREE(ipstr);
> +
> + addnhostsfile->hosts[idx].nhostnames++;
> +
> + return 0;
> +
> + alloc_error:
> + virReportOOMError();
> + VIR_FREE(ipstr);
> + return -1;
> +}
> +
> +static dnsmasqAddnHostsfile *
> +addnhostsNew(const char *name,
> + const char *config_dir)
> +{
> + int err;
> + dnsmasqAddnHostsfile *addnhostsfile;
> +
> + if (VIR_ALLOC(addnhostsfile)< 0) {
> + virReportOOMError();
> + return NULL;
> + }
> +
> + addnhostsfile->hosts = NULL;
> + addnhostsfile->nhosts = 0;
> +
> + if (virAsprintf(&addnhostsfile->path, "%s/%s.%s", config_dir, name,
> + DNSMASQ_ADDNHOSTSFILE_SUFFIX)< 0) {
> + virReportOOMError();
> + goto error;
> + }
> +
> + if ((err = virFileMakePath(config_dir))) {
> + virReportSystemError(err, _("cannot create config directory '%s'"),
> + config_dir);
> + goto error;
> + }
> +
> + return addnhostsfile;
> +
> + error:
> + addnhostsFree(addnhostsfile);
> + return NULL;
> +}
> +
> +static int
> +addnhostsWrite(const char *path,
> + dnsmasqAddnHost *hosts,
> + unsigned int nhosts)
> +{
> + char *tmp;
> + FILE *f;
> + bool istmp = true;
> + unsigned int i, ii;
> + int rc = 0;
> +
> + if (nhosts == 0)
> + return rc;
> +
> + if (virAsprintf(&tmp, "%s.new", path)< 0)
> + return -ENOMEM;
> +
> + if (!(f = fopen(tmp, "w"))) {
> + istmp = false;
> + if (!(f = fopen(path, "w"))) {
> + rc = errno;
> + goto cleanup;
> + }
> + }
> +
> + for (i = 0; i< nhosts; i++) {
> + if (fputs(hosts[i].ip, f) == EOF || fputc('\t', f) == EOF) {
> + rc = errno;
> + VIR_FORCE_FCLOSE(f);
> +
> + if (istmp)
> + unlink(tmp);
> +
> + goto cleanup;
> + }
> +
> + for (ii = 0; ii< hosts[i].nhostnames; ii++) {
> + if (fputs(hosts[i].hostnames[ii], f) == EOF || fputc('\t', f) == EOF) {
> + rc = errno;
> + VIR_FORCE_FCLOSE(f);
> +
> + if (istmp)
> + unlink(tmp);
> +
> + goto cleanup;
> + }
> + }
> +
> + if (fputc('\n', f) == EOF) {
> + rc = errno;
> + VIR_FORCE_FCLOSE(f);
> +
> + if (istmp)
> + unlink(tmp);
> +
> + goto cleanup;
> + }
> + }
> +
> + if (VIR_FCLOSE(f) == EOF) {
> + rc = errno;
> + goto cleanup;
> + }
> +
> + if (istmp) {
> + if (rename(tmp, path)< 0) {
> + rc = errno;
> + unlink(tmp);
> + goto cleanup;
> + }
> +
> + if (unlink(tmp)< 0) {
> + rc = errno;
> + goto cleanup;
> + }
> + }
> +
> + cleanup:
> + VIR_FREE(tmp);
> +
> + return rc;
> +}
> +
> +static int
> +addnhostsSave(dnsmasqAddnHostsfile *addnhostsfile)
> +{
> + int err = addnhostsWrite(addnhostsfile->path, addnhostsfile->hosts,
> + addnhostsfile->nhosts);
> +
> + if (err< 0) {
> + virReportSystemError(err, _("cannot write config file '%s'"),
> + addnhostsfile->path);
> + return -1;
> + }
> +
> + return 0;
> +}
> +
> +static int
> +genericFileDelete(char *path)
> +{
> + if (!virFileExists(path))
> + return 0;
> +
> + if (unlink(path)< 0) {
> + virReportSystemError(errno, _("cannot remove config file '%s'"),
> + path);
> + return -1;
> + }
> +
> + return 0;
> +}
> +
> +static void
> hostsfileFree(dnsmasqHostsfile *hostsfile)
> {
> unsigned int i;
> @@ -220,21 +450,6 @@ hostsfileSave(dnsmasqHostsfile *hostsfile)
> return 0;
> }
>
> -static int
> -hostsfileDelete(dnsmasqHostsfile *hostsfile)
> -{
> - if (!virFileExists(hostsfile->path))
> - return 0;
> -
> - if (unlink(hostsfile->path)< 0) {
> - virReportSystemError(errno, _("cannot remove config file '%s'"),
> - hostsfile->path);
> - return -1;
> - }
> -
> - return 0;
> -}
> -
> /**
> * dnsmasqContextNew:
> *
> @@ -255,6 +470,8 @@ dnsmasqContextNew(const char *network_name,
>
> if (!(ctx->hostsfile = hostsfileNew(network_name, config_dir)))
> goto error;
> + if (!(ctx->addnhostsfile = addnhostsNew(network_name, config_dir)))
> + goto error;
>
> return ctx;
>
> @@ -277,6 +494,8 @@ dnsmasqContextFree(dnsmasqContext *ctx)
>
> if (ctx->hostsfile)
> hostsfileFree(ctx->hostsfile);
> + if (ctx->addnhostsfile)
> + addnhostsFree(ctx->addnhostsfile);
>
> VIR_FREE(ctx);
> }
> @@ -300,6 +519,24 @@ dnsmasqAddDhcpHost(dnsmasqContext *ctx,
> hostsfileAdd(ctx->hostsfile, mac, ip, name);
> }
>
> +/*
> + * dnsmasqAddHost:
> + * @ctx: pointer to the dnsmasq context for each network
> + * @ip: pointer to the socket address contains ip of the host
> + * @name: pointer to the string contains hostname of the host
> + *
> + * Add additional host entry.
> + */
> +
> +void
> +dnsmasqAddHost(dnsmasqContext *ctx,
> + virSocketAddr *ip,
> + const char *name)
> +{
> + if (ctx->addnhostsfile)
> + addnhostsAdd(ctx->addnhostsfile, ip, name);
> +}
> +
> /**
> * dnsmasqSave:
> * @ctx: pointer to the dnsmasq context for each network
> @@ -309,10 +546,16 @@ dnsmasqAddDhcpHost(dnsmasqContext *ctx,
> int
> dnsmasqSave(const dnsmasqContext *ctx)
> {
> + int ret = 0;
> +
> if (ctx->hostsfile)
> - return hostsfileSave(ctx->hostsfile);
> + ret = hostsfileSave(ctx->hostsfile);
> + if (ret == 0) {
> + if (ctx->addnhostsfile)
> + ret = addnhostsSave(ctx->addnhostsfile);
> + }
>
> - return 0;
> + return ret;
> }
>
>
> @@ -325,10 +568,14 @@ dnsmasqSave(const dnsmasqContext *ctx)
> int
> dnsmasqDelete(const dnsmasqContext *ctx)
> {
> + int ret = 0;
> +
> if (ctx->hostsfile)
> - return hostsfileDelete(ctx->hostsfile);
> + ret = genericFileDelete(ctx->hostsfile->path);
> + if (ctx->addnhostsfile)
> + ret = genericFileDelete(ctx->addnhostsfile->path);
>
> - return 0;
> + return ret;
> }
>
> /**
> diff --git a/src/util/dnsmasq.h b/src/util/dnsmasq.h
> index 02a961f..3f6320a 100644
> --- a/src/util/dnsmasq.h
> +++ b/src/util/dnsmasq.h
> @@ -44,7 +44,24 @@ typedef struct
>
> typedef struct
> {
> - dnsmasqHostsfile *hostsfile;
> + unsigned int nhostnames;
> + char *ip;
> + char **hostnames;
The way you've defined your struct here is how you need to define
virNetworkDNSHostsDef in the next patch.
> +
> +} dnsmasqAddnHost;
> +
> +typedef struct
> +{
> + unsigned int nhosts;
> + dnsmasqAddnHost *hosts;
> +
> + char *path; /* Absolute path of dnsmasq's hostsfile. */
> +} dnsmasqAddnHostsfile;
> +
> +typedef struct
> +{
> + dnsmasqHostsfile *hostsfile;
> + dnsmasqAddnHostsfile *addnhostsfile;
> } dnsmasqContext;
>
> dnsmasqContext * dnsmasqContextNew(const char *network_name,
> @@ -54,6 +71,9 @@ void dnsmasqAddDhcpHost(dnsmasqContext *ctx,
> const char *mac,
> virSocketAddr *ip,
> const char *name);
> +void dnsmasqAddHost(dnsmasqContext *ctx,
> + virSocketAddr *ip,
> + const char *name);
> int dnsmasqSave(const dnsmasqContext *ctx);
> int dnsmasqDelete(const dnsmasqContext *ctx);
> int dnsmasqReload(pid_t pid);
ACK.
More information about the libvir-list
mailing list