mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-24 14:45:24 +00:00
Add dnsmasq module files
It implements an idea to save dhcp hosts' macaddr vs. ipaddr mappings to static file and make dnsmasq loading it with "--dhcp-hostsfile" option, originally suggested by Dan, and can address the problem that too many "--dhcp-host" args hitting ARG_MAX limit * src/util/dnsmasq.h src/util/dnsmasq.c: adds the 2 new files
This commit is contained in:
parent
4ce54ef5c7
commit
4ad65ab86a
341
src/util/dnsmasq.c
Normal file
341
src/util/dnsmasq.c
Normal file
@ -0,0 +1,341 @@
|
||||
/*
|
||||
* Copyright (C) 2007-2010 Red Hat, Inc.
|
||||
* Copyright (C) 2010 Satoru SATOH <satoru.satoh@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;
|
||||
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;
|
||||
}
|
59
src/util/dnsmasq.h
Normal file
59
src/util/dnsmasq.h
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2007-2010 Red Hat, Inc.
|
||||
* Copyright (C) 2010 Satoru SATOH <satoru.satoh@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__ */
|
Loading…
Reference in New Issue
Block a user