[libvirt] [PATCH 1/3] Add dnsmasq module (v2.1)

Satoru SATOH satoru.satoh at gmail.com
Sat Apr 24 02:22:15 UTC 2010


Ok, here is updated one. Could you please take a look at this?


This patch adds the files implements dnsmasq (hostsfile) module.

Signed-off-by: Satoru SATOH <satoru.satoh at gmail.com>

---
 src/util/dnsmasq.c |  341 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/util/dnsmasq.h |   59 +++++++++
 2 files changed, 400 insertions(+), 0 deletions(-)
 create mode 100644 src/util/dnsmasq.c
 create mode 100644 src/util/dnsmasq.h

diff --git a/src/util/dnsmasq.c b/src/util/dnsmasq.c
new file mode 100644
index 0000000..a6197be
--- /dev/null
+++ b/src/util/dnsmasq.c
@@ -0,0 +1,341 @@
+/*
+ * Copyright (C) 2007-2010 Red Hat, Inc.
+ * Copyright (C) 2010 Satoru SATOH <satoru.satoh at gmail.com>
+ *
+ * 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
+ *
+ * Based on iptables.c
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <signal.h>
+
+#ifdef HAVE_PATHS_H
+# include <paths.h>
+#endif
+
+#include "internal.h"
+#include "datatypes.h"
+#include "dnsmasq.h"
+#include "util.h"
+#include "memory.h"
+#include "virterror_internal.h"
+#include "logging.h"
+
+#define VIR_FROM_THIS VIR_FROM_NETWORK
+#define DNSMASQ_HOSTSFILE_SUFFIX "hostsfile"
+
+static void
+dhcphostFree(dnsmasqDhcpHost *host)
+{
+    VIR_FREE(host->host);
+}
+
+static void
+hostsfileFree(dnsmasqHostsfile *hostsfile)
+{
+    unsigned int i;
+
+    if (hostsfile->hosts) {
+        for (i = 0; i < hostsfile->nhosts; i++)
+            dhcphostFree(&hostsfile->hosts[i]);
+
+        VIR_FREE(hostsfile->hosts);
+
+        hostsfile->nhosts = 0;
+    }
+
+    VIR_FREE(hostsfile->path);
+
+    VIR_FREE(hostsfile);
+}
+
+static int
+hostsfileAdd(dnsmasqHostsfile *hostsfile,
+             const char *mac,
+             const char *ip,
+             const char *name)
+{
+    if (VIR_REALLOC_N(hostsfile->hosts, hostsfile->nhosts + 1) < 0)
+        goto alloc_error;
+
+    if (name) {
+        if (virAsprintf(&hostsfile->hosts[hostsfile->nhosts].host, "%s,%s,%s",
+                mac, ip, name) < 0) {
+            goto alloc_error;
+        }
+    } else {
+        if (virAsprintf(&hostsfile->hosts[hostsfile->nhosts].host, "%s,%s",
+                mac, ip) < 0) {
+            goto alloc_error;
+        }
+    }
+
+    hostsfile->nhosts++;
+
+    return 0;
+
+ alloc_error:
+    virReportSystemError(ENOMEM,
+        _("Failed to add dhcp host entry: mac=%s, ip=%s, name=%s\n"),
+        mac, ip, (name ? name : "(null)"));
+    return -1;
+}
+
+static dnsmasqHostsfile *
+hostsfileNew(const char *name,
+             const char *config_dir)
+{
+    int err;
+    dnsmasqHostsfile *hostsfile;
+
+    if (VIR_ALLOC(hostsfile) < 0)
+        return NULL;
+
+    hostsfile->hosts = NULL;
+    hostsfile->nhosts = 0;
+
+    if (virAsprintf(&hostsfile->path, "%s/%s.%s", config_dir, name,
+            DNSMASQ_HOSTSFILE_SUFFIX) < 0) {
+        goto error;
+    }
+
+    if ((err = virFileMakePath(config_dir))) {
+        virReportSystemError(err, _("cannot create config directory '%s'"),
+            config_dir);
+        goto error;
+    }
+
+    return hostsfile;
+
+ error:
+    hostsfileFree(hostsfile);
+    return NULL;
+}
+
+static int
+hostsfileWrite(const char *path,
+               dnsmasqDhcpHost *hosts,
+               unsigned int nhosts)
+{
+    char *tmp = NULL;
+    FILE *f;
+    bool istmp = true;
+    unsigned int i;
+    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].host, f) == EOF || fputc('\n', f) == EOF) {
+            rc = errno;
+            fclose(f);
+
+            if (istmp)
+                unlink(tmp);
+
+            goto cleanup;
+        }
+    }
+
+    if (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
+hostsfileSave(dnsmasqHostsfile *hostsfile)
+{
+    int err = hostsfileWrite(hostsfile->path, hostsfile->hosts,
+        hostsfile->nhosts);
+
+    if (err < 0) {
+        virReportSystemError(err, _("cannot write config file '%s'"),
+            hostsfile->path);
+        return -1;
+    }
+
+    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:
+ *
+ * Create a new Dnsmasq context
+ *
+ * Returns a pointer to the new structure or NULL in case of error
+ */
+dnsmasqContext *
+dnsmasqContextNew(const char *network_name,
+                  const char *config_dir)
+{
+    dnsmasqContext *ctx;
+
+    if (VIR_ALLOC(ctx) < 0)
+        return NULL;
+
+    if (!(ctx->hostsfile = hostsfileNew(network_name, config_dir)))
+        goto error;
+
+    return ctx;
+
+ error:
+    dnsmasqContextFree(ctx);
+    return NULL;
+}
+
+/**
+ * dnsmasqContextFree:
+ * @ctx: pointer to the dnsmasq context
+ *
+ * Free the resources associated with an dnsmasq context
+ */
+void
+dnsmasqContextFree(dnsmasqContext *ctx)
+{
+    if (!ctx)
+        return;
+
+    if (ctx->hostsfile)
+        hostsfileFree(ctx->hostsfile);
+
+    VIR_FREE(ctx);
+}
+
+/**
+ * dnsmasqAddDhcpHost:
+ * @ctx: pointer to the dnsmasq context for each network
+ * @mac: pointer to the string contains mac address of the host
+ * @ip: pointer to the string contains ip address of the host
+ * @name: pointer to the string contains hostname of the host or NULL
+ *
+ * Add dhcp-host entry.
+ */
+void
+dnsmasqAddDhcpHost(dnsmasqContext *ctx,
+                   const char *mac,
+                   const char *ip,
+                   const char *name)
+{
+    if (ctx->hostsfile)
+        hostsfileAdd(ctx->hostsfile, mac, ip, name);
+}
+
+/**
+ * dnsmasqSave:
+ * @ctx: pointer to the dnsmasq context for each network
+ *
+ * Saves all the configurations associated with a context to disk.
+ */
+int
+dnsmasqSave(const dnsmasqContext *ctx)
+{
+    if (ctx->hostsfile)
+        return hostsfileSave(ctx->hostsfile);
+
+    return 0;
+}
+
+
+/**
+ * dnsmasqDelete:
+ * @ctx: pointer to the dnsmasq context for each network
+ *
+ * Delete all the configuration files associated with a context.
+ */
+int
+dnsmasqDelete(const dnsmasqContext *ctx)
+{
+    if (ctx->hostsfile)
+        return hostsfileDelete(ctx->hostsfile);
+
+    return 0;
+}
+
+/**
+ * dnsmasqReload:
+ * @pid: the pid of the target dnsmasq process
+ *
+ * Reloads all the configurations associated to a context
+ */
+int
+dnsmasqReload(pid_t pid)
+{
+    if (kill(pid, SIGHUP) != 0) {
+        virReportSystemError(errno,
+            _("Failed to make dnsmasq (PID: %d) reload config files.\n"),
+            pid);
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/src/util/dnsmasq.h b/src/util/dnsmasq.h
new file mode 100644
index 0000000..121ccad
--- /dev/null
+++ b/src/util/dnsmasq.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2007-2010 Red Hat, Inc.
+ * Copyright (C) 2010 Satoru SATOH <satoru.satoh at gmail.com>
+ *
+ * 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
+ *
+ * based on iptables.h
+ */
+
+#ifndef __DNSMASQ_H__
+# define __DNSMASQ_H__
+
+typedef struct
+{
+    /*
+     * Each entry holds a string, "<mac_addr>,<hostname>,<ip_addr>" such as
+     * "01:23:45:67:89:0a,foo,10.0.0.3".
+     */
+    char *host;
+
+} dnsmasqDhcpHost;
+
+typedef struct
+{
+    unsigned int     nhosts;
+    dnsmasqDhcpHost *hosts;
+
+    char            *path;  /* Absolute path of dnsmasq's hostsfile. */
+} dnsmasqHostsfile;
+
+typedef struct
+{
+    dnsmasqHostsfile *hostsfile;
+} dnsmasqContext;
+
+dnsmasqContext * dnsmasqContextNew(const char *network_name,
+                                   const char *config_dir);
+void             dnsmasqContextFree(dnsmasqContext *ctx);
+void             dnsmasqAddDhcpHost(dnsmasqContext *ctx,
+                                    const char *mac,
+                                    const char *ip,
+                                    const char *name);
+int              dnsmasqSave(const dnsmasqContext *ctx);
+int              dnsmasqDelete(const dnsmasqContext *ctx);
+int              dnsmasqReload(pid_t pid);
+
+#endif /* __DNSMASQ_H__ */
-- 
1.6.2.5




More information about the libvir-list mailing list