This patch adds the files implements dnsmasq (hostsfile) module. Signed-off-by: Satoru SATOH <satoru.satoh@xxxxxxxxx> --- src/util/dnsmasq.c | 326 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/util/dnsmasq.h | 59 ++++++++++ 2 files changed, 385 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..b46654e --- /dev/null +++ b/src/util/dnsmasq.c @@ -0,0 +1,326 @@ +/* + * Copyright (C) 2010 Satoru SATOH <satoru.satoh@xxxxxxxxx> + * Copyright (C) 2007-2009 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, 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 "dnsmasq.h" +#include "util.h" +#include "memory.h" +#include "virterror_internal.h" +#include "logging.h" + +#define VIR_FROM_THIS VIR_FROM_NETWORK + +static void +dhcphostFree(dnsmasqDhcpHost *host) +{ + VIR_FREE(host->host); +} + +static void +hostsfileFree(dnsmasqHostsfile *hostsfile) +{ + int i; + + if (hostsfile->hosts) { + for (i = 0; i < hostsfile->nhosts; i++) + dhcphostFree(&hostsfile->hosts[i]); + + VIR_FREE(hostsfile->hosts); + + hostsfile->nhosts = 0; + } + + hostsfile->path[0] = '\0'; + + 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 ((err = virFileMakePath(config_dir))) { + virReportSystemError(err, _("cannot create config directory '%s'"), + config_dir); + goto error; + } + + if (virFileBuildPath(config_dir, name, ".hostsfile", hostsfile->path, + sizeof(hostsfile->path)) < 0) { + virReportSystemError(err, + _("config filename '%s/%s.%s' is too long"), + config_dir, name, ".hostsfile"); + goto error; + } + + return hostsfile; + + error: + hostsfileFree(hostsfile); + return NULL; +} + +static int +hostsfileWrite(const char *path, dnsmasqDhcpHost *hosts, int nhosts) +{ + char tmp[PATH_MAX]; + FILE *f; + int istmp; + int i; + + if (nhosts == 0 && unlink(path) == 0) + return 0; + + if (snprintf(tmp, PATH_MAX, "%s.new", path) >= PATH_MAX) + return EINVAL; + + istmp = 1; + + if (!(f = fopen(tmp, "w"))) { + istmp = 0; + if (!(f = fopen(path, "w"))) + return errno; + } + + for (i = 0; i < nhosts; i++) { + if (fputs(hosts[i].host, f) == EOF || fputc('\n', f) == EOF) { + fclose(f); + if (istmp) + unlink(tmp); + return errno; + } + } + + fclose(f); + + if (istmp && rename(tmp, path) < 0) { + unlink(tmp); + return errno; + } + + if (istmp) + unlink(tmp); + + return 0; +} + +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) reloading 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..987226b --- /dev/null +++ b/src/util/dnsmasq.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2010 Satoru SATOH <satoru.satoh@xxxxxxxxx> + * Copyright (C) 2007, 2008 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, 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 +{ + int nhosts; + dnsmasqDhcpHost *hosts; + + char path[PATH_MAX]; /* 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list