2008-10-10 13:57:13 +00:00
|
|
|
/*
|
2010-06-19 18:08:25 +00:00
|
|
|
* bridge_driver.c: core driver methods for managing network
|
2008-10-10 13:57:13 +00:00
|
|
|
*
|
2010-01-05 14:48:42 +00:00
|
|
|
* Copyright (C) 2006-2010 Red Hat, Inc.
|
2008-10-10 13:57:13 +00:00
|
|
|
* Copyright (C) 2006 Daniel P. Berrange
|
|
|
|
*
|
|
|
|
* 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
|
|
|
|
*
|
|
|
|
* Author: Daniel P. Berrange <berrange@redhat.com>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/poll.h>
|
|
|
|
#include <dirent.h>
|
|
|
|
#include <limits.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <sys/utsname.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <paths.h>
|
|
|
|
#include <pwd.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <sys/wait.h>
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
|
2008-11-04 22:30:33 +00:00
|
|
|
#include "virterror_internal.h"
|
2008-11-04 23:22:06 +00:00
|
|
|
#include "datatypes.h"
|
2009-09-15 17:52:58 +00:00
|
|
|
#include "bridge_driver.h"
|
2008-10-10 13:57:13 +00:00
|
|
|
#include "network_conf.h"
|
|
|
|
#include "driver.h"
|
|
|
|
#include "event.h"
|
|
|
|
#include "buf.h"
|
|
|
|
#include "util.h"
|
2010-12-10 18:54:48 +00:00
|
|
|
#include "command.h"
|
2008-10-10 13:57:13 +00:00
|
|
|
#include "memory.h"
|
|
|
|
#include "uuid.h"
|
|
|
|
#include "iptables.h"
|
|
|
|
#include "bridge.h"
|
2009-05-20 13:37:30 +00:00
|
|
|
#include "logging.h"
|
2010-04-26 14:07:25 +00:00
|
|
|
#include "dnsmasq.h"
|
2010-05-20 23:31:16 +00:00
|
|
|
#include "util/network.h"
|
2010-11-16 14:54:17 +00:00
|
|
|
#include "configmake.h"
|
2008-10-10 13:57:13 +00:00
|
|
|
|
2010-11-16 14:54:17 +00:00
|
|
|
#define NETWORK_PID_DIR LOCALSTATEDIR "/run/libvirt/network"
|
|
|
|
#define NETWORK_STATE_DIR LOCALSTATEDIR "/lib/libvirt/network"
|
2009-01-20 17:13:33 +00:00
|
|
|
|
2010-11-16 14:54:17 +00:00
|
|
|
#define DNSMASQ_STATE_DIR LOCALSTATEDIR "/lib/libvirt/dnsmasq"
|
2010-12-20 06:14:11 +00:00
|
|
|
#define RADVD_STATE_DIR LOCALSTATEDIR "/lib/libvirt/radvd"
|
2010-04-26 14:07:25 +00:00
|
|
|
|
2009-01-20 17:13:33 +00:00
|
|
|
#define VIR_FROM_THIS VIR_FROM_NETWORK
|
|
|
|
|
2010-03-01 23:38:28 +00:00
|
|
|
#define networkReportError(code, ...) \
|
2010-02-10 10:22:52 +00:00
|
|
|
virReportErrorHelper(NULL, VIR_FROM_NETWORK, code, __FILE__, \
|
2010-03-01 23:38:28 +00:00
|
|
|
__FUNCTION__, __LINE__, __VA_ARGS__)
|
2010-02-10 10:22:52 +00:00
|
|
|
|
2008-10-10 13:57:13 +00:00
|
|
|
/* Main driver state */
|
|
|
|
struct network_driver {
|
2009-01-15 19:56:05 +00:00
|
|
|
virMutex lock;
|
2008-12-04 21:38:38 +00:00
|
|
|
|
2008-10-10 14:50:26 +00:00
|
|
|
virNetworkObjList networks;
|
2008-10-10 13:57:13 +00:00
|
|
|
|
|
|
|
iptablesContext *iptables;
|
|
|
|
brControl *brctl;
|
|
|
|
char *networkConfigDir;
|
|
|
|
char *networkAutostartDir;
|
|
|
|
char *logDir;
|
|
|
|
};
|
|
|
|
|
2008-12-04 21:38:38 +00:00
|
|
|
|
|
|
|
static void networkDriverLock(struct network_driver *driver)
|
|
|
|
{
|
2009-01-15 19:56:05 +00:00
|
|
|
virMutexLock(&driver->lock);
|
2008-12-04 21:38:38 +00:00
|
|
|
}
|
|
|
|
static void networkDriverUnlock(struct network_driver *driver)
|
|
|
|
{
|
2009-01-15 19:56:05 +00:00
|
|
|
virMutexUnlock(&driver->lock);
|
2008-12-04 21:38:38 +00:00
|
|
|
}
|
|
|
|
|
2008-10-10 13:57:13 +00:00
|
|
|
static int networkShutdown(void);
|
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
static int networkStartNetworkDaemon(struct network_driver *driver,
|
|
|
|
virNetworkObjPtr network);
|
2008-10-10 13:57:13 +00:00
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
static int networkShutdownNetworkDaemon(struct network_driver *driver,
|
|
|
|
virNetworkObjPtr network);
|
2008-10-10 13:57:13 +00:00
|
|
|
|
2009-12-10 11:27:17 +00:00
|
|
|
static void networkReloadIptablesRules(struct network_driver *driver);
|
|
|
|
|
2008-10-10 13:57:13 +00:00
|
|
|
static struct network_driver *driverState = NULL;
|
|
|
|
|
2010-12-20 06:14:11 +00:00
|
|
|
static char *
|
|
|
|
networkRadvdPidfileBasename(const char *netname)
|
|
|
|
{
|
|
|
|
/* this is simple but we want to be sure it's consistently done */
|
|
|
|
char *pidfilebase;
|
|
|
|
|
|
|
|
virAsprintf(&pidfilebase, "%s-radvd", netname);
|
|
|
|
return pidfilebase;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *
|
|
|
|
networkRadvdConfigFileName(const char *netname)
|
|
|
|
{
|
|
|
|
char *configfile;
|
|
|
|
|
|
|
|
virAsprintf(&configfile, RADVD_STATE_DIR "/%s-radvd.conf",
|
|
|
|
netname);
|
|
|
|
return configfile;
|
|
|
|
}
|
2008-10-10 13:57:13 +00:00
|
|
|
|
2009-01-20 22:36:10 +00:00
|
|
|
static void
|
|
|
|
networkFindActiveConfigs(struct network_driver *driver) {
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
for (i = 0 ; i < driver->networks.count ; i++) {
|
|
|
|
virNetworkObjPtr obj = driver->networks.objs[i];
|
|
|
|
virNetworkDefPtr tmp;
|
|
|
|
char *config;
|
|
|
|
|
|
|
|
virNetworkObjLock(obj);
|
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
if ((config = virNetworkConfigFile(NETWORK_STATE_DIR,
|
2009-01-20 22:36:10 +00:00
|
|
|
obj->def->name)) == NULL) {
|
|
|
|
virNetworkObjUnlock(obj);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (access(config, R_OK) < 0) {
|
|
|
|
VIR_FREE(config);
|
|
|
|
virNetworkObjUnlock(obj);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Try and load the live config */
|
2010-02-10 10:22:52 +00:00
|
|
|
tmp = virNetworkDefParseFile(config);
|
2009-01-20 22:36:10 +00:00
|
|
|
VIR_FREE(config);
|
|
|
|
if (tmp) {
|
|
|
|
obj->newDef = obj->def;
|
|
|
|
obj->def = tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If bridge exists, then mark it active */
|
|
|
|
if (obj->def->bridge &&
|
|
|
|
brHasBridge(driver->brctl, obj->def->bridge) == 0) {
|
|
|
|
obj->active = 1;
|
|
|
|
|
2010-12-20 06:14:11 +00:00
|
|
|
/* Try and read dnsmasq/radvd pids if any */
|
|
|
|
if (obj->def->ips && (obj->def->nips > 0)) {
|
|
|
|
char *pidpath, *radvdpidbase;
|
|
|
|
|
|
|
|
if (virFileReadPid(NETWORK_PID_DIR, obj->def->name,
|
|
|
|
&obj->dnsmasqPid) == 0) {
|
|
|
|
/* Check that it's still alive */
|
|
|
|
if (kill(obj->dnsmasqPid, 0) != 0)
|
|
|
|
obj->dnsmasqPid = -1;
|
|
|
|
if (virAsprintf(&pidpath, "/proc/%d/exe", obj->dnsmasqPid) < 0) {
|
|
|
|
virReportOOMError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
if (virFileLinkPointsTo(pidpath, DNSMASQ) == 0)
|
|
|
|
obj->dnsmasqPid = -1;
|
|
|
|
VIR_FREE(pidpath);
|
|
|
|
}
|
2009-01-20 22:36:10 +00:00
|
|
|
|
2010-12-20 06:14:11 +00:00
|
|
|
if (!(radvdpidbase = networkRadvdPidfileBasename(obj->def->name))) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2009-10-16 10:09:13 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2010-12-20 06:14:11 +00:00
|
|
|
if (virFileReadPid(NETWORK_PID_DIR, radvdpidbase,
|
|
|
|
&obj->radvdPid) == 0) {
|
|
|
|
/* Check that it's still alive */
|
|
|
|
if (kill(obj->radvdPid, 0) != 0)
|
|
|
|
obj->radvdPid = -1;
|
|
|
|
if (virAsprintf(&pidpath, "/proc/%d/exe", obj->radvdPid) < 0) {
|
|
|
|
virReportOOMError();
|
|
|
|
VIR_FREE(radvdpidbase);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
if (virFileLinkPointsTo(pidpath, RADVD) == 0)
|
|
|
|
obj->radvdPid = -1;
|
|
|
|
VIR_FREE(pidpath);
|
|
|
|
}
|
|
|
|
VIR_FREE(radvdpidbase);
|
2009-01-20 22:36:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-10-16 10:09:13 +00:00
|
|
|
cleanup:
|
2009-01-20 22:36:10 +00:00
|
|
|
virNetworkObjUnlock(obj);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-10 14:50:26 +00:00
|
|
|
static void
|
|
|
|
networkAutostartConfigs(struct network_driver *driver) {
|
|
|
|
unsigned int i;
|
2008-10-10 13:57:13 +00:00
|
|
|
|
2008-10-10 14:50:26 +00:00
|
|
|
for (i = 0 ; i < driver->networks.count ; i++) {
|
2008-12-04 21:38:38 +00:00
|
|
|
virNetworkObjLock(driver->networks.objs[i]);
|
2008-10-10 14:50:26 +00:00
|
|
|
if (driver->networks.objs[i]->autostart &&
|
Rename internal APis
Rename virDomainIsActive to virDomainObjIsActive, and
virInterfaceIsActive to virInterfaceObjIsActive and finally
virNetworkIsActive to virNetworkObjIsActive.
* src/conf/domain_conf.c, src/conf/domain_conf.h,
src/conf/interface_conf.h, src/conf/network_conf.c,
src/conf/network_conf.h, src/lxc/lxc_driver.c,
src/network/bridge_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_driver.c, src/qemu/qemu_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c: Update for
renamed APIs.
2009-10-20 14:51:03 +00:00
|
|
|
!virNetworkObjIsActive(driver->networks.objs[i]) &&
|
2010-02-10 10:22:52 +00:00
|
|
|
networkStartNetworkDaemon(driver, driver->networks.objs[i]) < 0) {
|
2009-05-20 13:37:30 +00:00
|
|
|
/* failed to start but already logged */
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
2008-12-04 21:38:38 +00:00
|
|
|
virNetworkObjUnlock(driver->networks.objs[i]);
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* networkStartup:
|
|
|
|
*
|
|
|
|
* Initialization function for the QEmu daemon
|
|
|
|
*/
|
|
|
|
static int
|
2009-06-12 13:20:13 +00:00
|
|
|
networkStartup(int privileged) {
|
2008-10-10 13:57:13 +00:00
|
|
|
uid_t uid = geteuid();
|
|
|
|
char *base = NULL;
|
2009-01-20 22:36:10 +00:00
|
|
|
int err;
|
2008-10-10 13:57:13 +00:00
|
|
|
|
|
|
|
if (VIR_ALLOC(driverState) < 0)
|
2008-12-04 21:37:52 +00:00
|
|
|
goto error;
|
2008-10-10 13:57:13 +00:00
|
|
|
|
2009-01-15 19:56:05 +00:00
|
|
|
if (virMutexInit(&driverState->lock) < 0) {
|
|
|
|
VIR_FREE(driverState);
|
|
|
|
goto error;
|
|
|
|
}
|
2008-12-04 21:38:38 +00:00
|
|
|
networkDriverLock(driverState);
|
|
|
|
|
2009-06-12 13:20:13 +00:00
|
|
|
if (privileged) {
|
2008-12-23 13:03:29 +00:00
|
|
|
if (virAsprintf(&driverState->logDir,
|
2010-11-16 14:54:17 +00:00
|
|
|
"%s/log/libvirt/qemu", LOCALSTATEDIR) == -1)
|
2008-10-10 13:57:13 +00:00
|
|
|
goto out_of_memory;
|
|
|
|
|
2010-11-16 14:54:17 +00:00
|
|
|
if ((base = strdup (SYSCONFDIR "/libvirt")) == NULL)
|
2008-10-10 13:57:13 +00:00
|
|
|
goto out_of_memory;
|
|
|
|
} else {
|
2010-02-04 22:41:52 +00:00
|
|
|
char *userdir = virGetUserDirectory(uid);
|
2009-01-22 19:41:48 +00:00
|
|
|
|
|
|
|
if (!userdir)
|
|
|
|
goto error;
|
2008-10-10 13:57:13 +00:00
|
|
|
|
2008-12-23 13:03:29 +00:00
|
|
|
if (virAsprintf(&driverState->logDir,
|
2009-01-22 19:41:48 +00:00
|
|
|
"%s/.libvirt/qemu/log", userdir) == -1) {
|
|
|
|
VIR_FREE(userdir);
|
2008-10-10 13:57:13 +00:00
|
|
|
goto out_of_memory;
|
2009-01-22 19:41:48 +00:00
|
|
|
}
|
2008-10-10 13:57:13 +00:00
|
|
|
|
2009-01-22 19:41:48 +00:00
|
|
|
if (virAsprintf(&base, "%s/.libvirt", userdir) == -1) {
|
|
|
|
VIR_FREE(userdir);
|
2008-10-10 13:57:13 +00:00
|
|
|
goto out_of_memory;
|
|
|
|
}
|
2009-01-22 19:41:48 +00:00
|
|
|
VIR_FREE(userdir);
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Configuration paths are either ~/.libvirt/qemu/... (session) or
|
|
|
|
* /etc/libvirt/qemu/... (system).
|
|
|
|
*/
|
2008-12-23 13:03:29 +00:00
|
|
|
if (virAsprintf(&driverState->networkConfigDir, "%s/qemu/networks", base) == -1)
|
2008-10-10 13:57:13 +00:00
|
|
|
goto out_of_memory;
|
|
|
|
|
2008-12-23 13:03:29 +00:00
|
|
|
if (virAsprintf(&driverState->networkAutostartDir, "%s/qemu/networks/autostart",
|
|
|
|
base) == -1)
|
2008-10-10 13:57:13 +00:00
|
|
|
goto out_of_memory;
|
|
|
|
|
|
|
|
VIR_FREE(base);
|
|
|
|
|
2009-01-20 22:36:10 +00:00
|
|
|
if ((err = brInit(&driverState->brctl))) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(err, "%s",
|
2009-01-20 22:36:10 +00:00
|
|
|
_("cannot initialize bridge support"));
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(driverState->iptables = iptablesContextNew())) {
|
2009-05-20 13:37:30 +00:00
|
|
|
goto out_of_memory;
|
2009-01-20 22:36:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
if (virNetworkLoadAllConfigs(&driverState->networks,
|
2008-10-10 13:57:13 +00:00
|
|
|
driverState->networkConfigDir,
|
2008-12-04 21:37:52 +00:00
|
|
|
driverState->networkAutostartDir) < 0)
|
|
|
|
goto error;
|
|
|
|
|
2009-01-20 22:36:10 +00:00
|
|
|
networkFindActiveConfigs(driverState);
|
2009-12-10 11:27:17 +00:00
|
|
|
networkReloadIptablesRules(driverState);
|
2008-10-10 13:57:13 +00:00
|
|
|
networkAutostartConfigs(driverState);
|
|
|
|
|
2008-12-04 21:38:38 +00:00
|
|
|
networkDriverUnlock(driverState);
|
|
|
|
|
2008-10-10 13:57:13 +00:00
|
|
|
return 0;
|
|
|
|
|
2008-12-04 21:37:52 +00:00
|
|
|
out_of_memory:
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2008-12-04 21:37:52 +00:00
|
|
|
|
|
|
|
error:
|
2008-12-04 21:38:38 +00:00
|
|
|
if (driverState)
|
|
|
|
networkDriverUnlock(driverState);
|
|
|
|
|
2008-10-10 13:57:13 +00:00
|
|
|
VIR_FREE(base);
|
2008-12-04 21:37:52 +00:00
|
|
|
networkShutdown();
|
2008-10-10 13:57:13 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* networkReload:
|
|
|
|
*
|
|
|
|
* Function to restart the QEmu daemon, it will recheck the configuration
|
|
|
|
* files and update its state and the networking
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
networkReload(void) {
|
2008-10-10 14:50:26 +00:00
|
|
|
if (!driverState)
|
|
|
|
return 0;
|
|
|
|
|
2008-12-04 21:38:38 +00:00
|
|
|
networkDriverLock(driverState);
|
2010-02-10 10:22:52 +00:00
|
|
|
virNetworkLoadAllConfigs(&driverState->networks,
|
2008-10-10 13:57:13 +00:00
|
|
|
driverState->networkConfigDir,
|
|
|
|
driverState->networkAutostartDir);
|
2009-12-10 11:27:17 +00:00
|
|
|
networkReloadIptablesRules(driverState);
|
2008-10-10 13:57:13 +00:00
|
|
|
networkAutostartConfigs(driverState);
|
2008-12-04 21:38:38 +00:00
|
|
|
networkDriverUnlock(driverState);
|
2008-10-10 13:57:13 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* networkActive:
|
|
|
|
*
|
|
|
|
* Checks if the QEmu daemon is active, i.e. has an active domain or
|
|
|
|
* an active network
|
|
|
|
*
|
|
|
|
* Returns 1 if active, 0 otherwise
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
networkActive(void) {
|
2008-10-10 14:50:26 +00:00
|
|
|
unsigned int i;
|
2008-12-04 21:37:52 +00:00
|
|
|
int active = 0;
|
2008-10-10 13:57:13 +00:00
|
|
|
|
2008-10-10 14:50:26 +00:00
|
|
|
if (!driverState)
|
|
|
|
return 0;
|
|
|
|
|
2008-12-04 21:38:38 +00:00
|
|
|
networkDriverLock(driverState);
|
2008-12-04 21:37:52 +00:00
|
|
|
for (i = 0 ; i < driverState->networks.count ; i++) {
|
|
|
|
virNetworkObjPtr net = driverState->networks.objs[i];
|
2008-12-04 21:38:38 +00:00
|
|
|
virNetworkObjLock(net);
|
Rename internal APis
Rename virDomainIsActive to virDomainObjIsActive, and
virInterfaceIsActive to virInterfaceObjIsActive and finally
virNetworkIsActive to virNetworkObjIsActive.
* src/conf/domain_conf.c, src/conf/domain_conf.h,
src/conf/interface_conf.h, src/conf/network_conf.c,
src/conf/network_conf.h, src/lxc/lxc_driver.c,
src/network/bridge_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_driver.c, src/qemu/qemu_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c: Update for
renamed APIs.
2009-10-20 14:51:03 +00:00
|
|
|
if (virNetworkObjIsActive(net))
|
2008-12-04 21:37:52 +00:00
|
|
|
active = 1;
|
2008-12-04 21:38:38 +00:00
|
|
|
virNetworkObjUnlock(net);
|
2008-12-04 21:37:52 +00:00
|
|
|
}
|
2008-12-04 21:38:38 +00:00
|
|
|
networkDriverUnlock(driverState);
|
2008-12-04 21:37:52 +00:00
|
|
|
return active;
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* networkShutdown:
|
|
|
|
*
|
|
|
|
* Shutdown the QEmu daemon, it will stop all active domains and networks
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
networkShutdown(void) {
|
|
|
|
if (!driverState)
|
|
|
|
return -1;
|
|
|
|
|
2008-12-04 21:38:38 +00:00
|
|
|
networkDriverLock(driverState);
|
|
|
|
|
2008-10-10 13:57:13 +00:00
|
|
|
/* free inactive networks */
|
2008-10-10 14:50:26 +00:00
|
|
|
virNetworkObjListFree(&driverState->networks);
|
2008-10-10 13:57:13 +00:00
|
|
|
|
|
|
|
VIR_FREE(driverState->logDir);
|
|
|
|
VIR_FREE(driverState->networkConfigDir);
|
|
|
|
VIR_FREE(driverState->networkAutostartDir);
|
|
|
|
|
|
|
|
if (driverState->brctl)
|
|
|
|
brShutdown(driverState->brctl);
|
|
|
|
if (driverState->iptables)
|
|
|
|
iptablesContextFree(driverState->iptables);
|
|
|
|
|
2008-12-04 21:38:38 +00:00
|
|
|
networkDriverUnlock(driverState);
|
2009-01-15 19:56:05 +00:00
|
|
|
virMutexDestroy(&driverState->lock);
|
2008-12-04 21:38:38 +00:00
|
|
|
|
2008-10-10 13:57:13 +00:00
|
|
|
VIR_FREE(driverState);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-04-26 14:07:25 +00:00
|
|
|
static int
|
2010-11-17 18:36:19 +00:00
|
|
|
networkSaveDnsmasqHostsfile(virNetworkIpDefPtr ipdef,
|
2010-04-26 14:07:25 +00:00
|
|
|
dnsmasqContext *dctx,
|
|
|
|
bool force)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
if (! force && virFileExists(dctx->hostsfile->path))
|
2010-12-15 06:49:29 +00:00
|
|
|
return 0;
|
2010-04-26 14:07:25 +00:00
|
|
|
|
2010-11-17 18:36:19 +00:00
|
|
|
for (i = 0; i < ipdef->nhosts; i++) {
|
|
|
|
virNetworkDHCPHostDefPtr host = &(ipdef->hosts[i]);
|
Convert virNetwork to use virSocketAddr everywhere
Instead of storing the IP address string in virNetwork related
structs, store the parsed virSocketAddr. This will make it
easier to add IPv6 support in the future, by letting driver
code directly check what address family is present
* src/conf/network_conf.c, src/conf/network_conf.h,
src/network/bridge_driver.c: Convert to use virSocketAddr
in virNetwork, instead of char *.
* src/util/bridge.c, src/util/bridge.h,
src/util/dnsmasq.c, src/util/dnsmasq.h,
src/util/iptables.c, src/util/iptables.h: Convert to
take a virSocketAddr instead of char * for any IP
address parameters
* src/util/network.h: Add macros to determine if an address
is set, and what address family is set.
2010-10-21 12:14:33 +00:00
|
|
|
if ((host->mac) && VIR_SOCKET_HAS_ADDR(&host->ip))
|
|
|
|
dnsmasqAddDhcpHost(dctx, host->mac, &host->ip, host->name);
|
2010-04-26 14:07:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (dnsmasqSave(dctx) < 0)
|
2010-12-15 06:49:29 +00:00
|
|
|
return -1;
|
2010-04-26 14:07:25 +00:00
|
|
|
|
2010-12-15 06:49:29 +00:00
|
|
|
return 0;
|
2010-04-26 14:07:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-10 13:57:13 +00:00
|
|
|
static int
|
2010-02-04 18:19:08 +00:00
|
|
|
networkBuildDnsmasqArgv(virNetworkObjPtr network,
|
2010-11-17 18:36:19 +00:00
|
|
|
virNetworkIpDefPtr ipdef,
|
2009-01-20 22:36:10 +00:00
|
|
|
const char *pidfile,
|
2010-12-10 18:54:48 +00:00
|
|
|
virCommandPtr cmd) {
|
|
|
|
int r, ret = -1;
|
2009-11-06 16:53:45 +00:00
|
|
|
int nbleases = 0;
|
2010-12-10 18:54:48 +00:00
|
|
|
char *bridgeaddr;
|
2009-01-20 22:36:10 +00:00
|
|
|
|
2010-11-17 18:36:19 +00:00
|
|
|
if (!(bridgeaddr = virSocketFormatAddr(&ipdef->address)))
|
2010-12-10 18:54:48 +00:00
|
|
|
goto cleanup;
|
2009-01-20 22:36:10 +00:00
|
|
|
/*
|
2010-12-10 18:54:48 +00:00
|
|
|
* NB, be careful about syntax for dnsmasq options in long format.
|
2009-01-20 22:36:10 +00:00
|
|
|
*
|
|
|
|
* If the flag has a mandatory argument, it can be given using
|
|
|
|
* either syntax:
|
|
|
|
*
|
|
|
|
* --foo bar
|
|
|
|
* --foo=bar
|
|
|
|
*
|
|
|
|
* If the flag has a optional argument, it *must* be given using
|
|
|
|
* the syntax:
|
|
|
|
*
|
|
|
|
* --foo=bar
|
|
|
|
*
|
|
|
|
* It is hard to determine whether a flag is optional or not,
|
2010-12-10 18:54:48 +00:00
|
|
|
* without reading the dnsmasq source :-( The manpage is not
|
|
|
|
* very explicit on this.
|
2009-01-20 22:36:10 +00:00
|
|
|
*/
|
2008-10-10 13:57:13 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Needed to ensure dnsmasq uses same algorithm for processing
|
|
|
|
* multiple namedriver entries in /etc/resolv.conf as GLibC.
|
|
|
|
*/
|
2010-12-10 18:54:48 +00:00
|
|
|
virCommandAddArgList(cmd, "--strict-order", "--bind-interfaces", NULL);
|
2008-10-10 13:57:13 +00:00
|
|
|
|
2010-12-10 18:54:48 +00:00
|
|
|
if (network->def->domain)
|
|
|
|
virCommandAddArgList(cmd, "--domain", network->def->domain, NULL);
|
2008-10-10 13:57:13 +00:00
|
|
|
|
2010-12-10 18:54:48 +00:00
|
|
|
virCommandAddArgPair(cmd, "--pid-file", pidfile);
|
2008-10-10 13:57:13 +00:00
|
|
|
|
2010-12-10 18:54:48 +00:00
|
|
|
/* *no* conf file */
|
|
|
|
virCommandAddArgList(cmd, "--conf-file=", "", NULL);
|
2008-10-10 13:57:13 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* XXX does not actually work, due to some kind of
|
|
|
|
* race condition setting up ipv6 addresses on the
|
|
|
|
* interface. A sleep(10) makes it work, but that's
|
|
|
|
* clearly not practical
|
|
|
|
*
|
2010-12-10 18:54:48 +00:00
|
|
|
* virCommandAddArg(cmd, "--interface");
|
2010-11-17 18:36:19 +00:00
|
|
|
* virCommandAddArg(cmd, ipdef->bridge);
|
2008-10-10 13:57:13 +00:00
|
|
|
*/
|
2010-12-10 18:54:48 +00:00
|
|
|
virCommandAddArgList(cmd,
|
|
|
|
"--listen-address", bridgeaddr,
|
|
|
|
"--except-interface", "lo",
|
|
|
|
NULL);
|
2008-10-10 13:57:13 +00:00
|
|
|
|
2010-11-17 18:36:19 +00:00
|
|
|
for (r = 0 ; r < ipdef->nranges ; r++) {
|
|
|
|
char *saddr = virSocketFormatAddr(&ipdef->ranges[r].start);
|
Convert virNetwork to use virSocketAddr everywhere
Instead of storing the IP address string in virNetwork related
structs, store the parsed virSocketAddr. This will make it
easier to add IPv6 support in the future, by letting driver
code directly check what address family is present
* src/conf/network_conf.c, src/conf/network_conf.h,
src/network/bridge_driver.c: Convert to use virSocketAddr
in virNetwork, instead of char *.
* src/util/bridge.c, src/util/bridge.h,
src/util/dnsmasq.c, src/util/dnsmasq.h,
src/util/iptables.c, src/util/iptables.h: Convert to
take a virSocketAddr instead of char * for any IP
address parameters
* src/util/network.h: Add macros to determine if an address
is set, and what address family is set.
2010-10-21 12:14:33 +00:00
|
|
|
if (!saddr)
|
2010-12-10 18:54:48 +00:00
|
|
|
goto cleanup;
|
2010-11-17 18:36:19 +00:00
|
|
|
char *eaddr = virSocketFormatAddr(&ipdef->ranges[r].end);
|
Convert virNetwork to use virSocketAddr everywhere
Instead of storing the IP address string in virNetwork related
structs, store the parsed virSocketAddr. This will make it
easier to add IPv6 support in the future, by letting driver
code directly check what address family is present
* src/conf/network_conf.c, src/conf/network_conf.h,
src/network/bridge_driver.c: Convert to use virSocketAddr
in virNetwork, instead of char *.
* src/util/bridge.c, src/util/bridge.h,
src/util/dnsmasq.c, src/util/dnsmasq.h,
src/util/iptables.c, src/util/iptables.h: Convert to
take a virSocketAddr instead of char * for any IP
address parameters
* src/util/network.h: Add macros to determine if an address
is set, and what address family is set.
2010-10-21 12:14:33 +00:00
|
|
|
if (!eaddr) {
|
|
|
|
VIR_FREE(saddr);
|
2010-12-10 18:54:48 +00:00
|
|
|
goto cleanup;
|
Convert virNetwork to use virSocketAddr everywhere
Instead of storing the IP address string in virNetwork related
structs, store the parsed virSocketAddr. This will make it
easier to add IPv6 support in the future, by letting driver
code directly check what address family is present
* src/conf/network_conf.c, src/conf/network_conf.h,
src/network/bridge_driver.c: Convert to use virSocketAddr
in virNetwork, instead of char *.
* src/util/bridge.c, src/util/bridge.h,
src/util/dnsmasq.c, src/util/dnsmasq.h,
src/util/iptables.c, src/util/iptables.h: Convert to
take a virSocketAddr instead of char * for any IP
address parameters
* src/util/network.h: Add macros to determine if an address
is set, and what address family is set.
2010-10-21 12:14:33 +00:00
|
|
|
}
|
2010-12-10 18:54:48 +00:00
|
|
|
virCommandAddArg(cmd, "--dhcp-range");
|
|
|
|
virCommandAddArgFormat(cmd, "%s,%s", saddr, eaddr);
|
Convert virNetwork to use virSocketAddr everywhere
Instead of storing the IP address string in virNetwork related
structs, store the parsed virSocketAddr. This will make it
easier to add IPv6 support in the future, by letting driver
code directly check what address family is present
* src/conf/network_conf.c, src/conf/network_conf.h,
src/network/bridge_driver.c: Convert to use virSocketAddr
in virNetwork, instead of char *.
* src/util/bridge.c, src/util/bridge.h,
src/util/dnsmasq.c, src/util/dnsmasq.h,
src/util/iptables.c, src/util/iptables.h: Convert to
take a virSocketAddr instead of char * for any IP
address parameters
* src/util/network.h: Add macros to determine if an address
is set, and what address family is set.
2010-10-21 12:14:33 +00:00
|
|
|
VIR_FREE(saddr);
|
|
|
|
VIR_FREE(eaddr);
|
2010-11-17 18:36:19 +00:00
|
|
|
nbleases += virSocketGetRange(&ipdef->ranges[r].start,
|
|
|
|
&ipdef->ranges[r].end);
|
2009-11-06 16:53:45 +00:00
|
|
|
}
|
|
|
|
|
2010-12-10 18:54:48 +00:00
|
|
|
/*
|
|
|
|
* For static-only DHCP, i.e. with no range but at least one host element,
|
|
|
|
* we have to add a special --dhcp-range option to enable the service in
|
|
|
|
* dnsmasq.
|
|
|
|
*/
|
2010-11-17 18:36:19 +00:00
|
|
|
if (!ipdef->nranges && ipdef->nhosts) {
|
2010-12-10 18:54:48 +00:00
|
|
|
virCommandAddArg(cmd, "--dhcp-range");
|
|
|
|
virCommandAddArgFormat(cmd, "%s,static", bridgeaddr);
|
2010-09-09 14:00:08 +00:00
|
|
|
}
|
|
|
|
|
2010-11-17 18:36:19 +00:00
|
|
|
if (ipdef->nranges > 0) {
|
2010-12-10 18:54:48 +00:00
|
|
|
virCommandAddArgFormat(cmd, "--dhcp-lease-max=%d", nbleases);
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
|
|
|
|
2010-11-17 18:36:19 +00:00
|
|
|
if (ipdef->nranges || ipdef->nhosts)
|
2010-12-10 18:54:48 +00:00
|
|
|
virCommandAddArg(cmd, "--dhcp-no-override");
|
2010-09-09 14:00:08 +00:00
|
|
|
|
2010-11-17 18:36:19 +00:00
|
|
|
if (ipdef->nhosts > 0) {
|
2010-12-10 18:54:48 +00:00
|
|
|
dnsmasqContext *dctx = dnsmasqContextNew(network->def->name,
|
|
|
|
DNSMASQ_STATE_DIR);
|
|
|
|
if (dctx == NULL) {
|
|
|
|
virReportOOMError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2010-04-26 14:07:25 +00:00
|
|
|
|
2011-01-06 08:14:58 +00:00
|
|
|
if (networkSaveDnsmasqHostsfile(ipdef, dctx, false) == 0) {
|
2010-12-10 18:54:48 +00:00
|
|
|
virCommandAddArgPair(cmd, "--dhcp-hostsfile",
|
|
|
|
dctx->hostsfile->path);
|
2010-04-26 14:07:25 +00:00
|
|
|
}
|
|
|
|
dnsmasqContextFree(dctx);
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
|
|
|
|
2010-11-17 18:36:19 +00:00
|
|
|
if (ipdef->tftproot) {
|
2010-12-10 18:54:48 +00:00
|
|
|
virCommandAddArgList(cmd, "--enable-tftp",
|
2010-11-17 18:36:19 +00:00
|
|
|
"--tftp-root", ipdef->tftproot,
|
2010-12-10 18:54:48 +00:00
|
|
|
NULL);
|
2009-09-21 20:50:25 +00:00
|
|
|
}
|
2010-11-17 18:36:19 +00:00
|
|
|
if (ipdef->bootfile) {
|
2010-12-10 18:54:48 +00:00
|
|
|
virCommandAddArg(cmd, "--dhcp-boot");
|
2010-11-17 18:36:19 +00:00
|
|
|
if (VIR_SOCKET_HAS_ADDR(&ipdef->bootserver)) {
|
|
|
|
char *bootserver = virSocketFormatAddr(&ipdef->bootserver);
|
2010-12-10 18:54:48 +00:00
|
|
|
|
|
|
|
if (!bootserver)
|
|
|
|
goto cleanup;
|
|
|
|
virCommandAddArgFormat(cmd, "%s%s%s",
|
2010-11-17 18:36:19 +00:00
|
|
|
ipdef->bootfile, ",,", bootserver);
|
2010-12-10 18:54:48 +00:00
|
|
|
VIR_FREE(bootserver);
|
|
|
|
} else {
|
2010-11-17 18:36:19 +00:00
|
|
|
virCommandAddArg(cmd, ipdef->bootfile);
|
Convert virNetwork to use virSocketAddr everywhere
Instead of storing the IP address string in virNetwork related
structs, store the parsed virSocketAddr. This will make it
easier to add IPv6 support in the future, by letting driver
code directly check what address family is present
* src/conf/network_conf.c, src/conf/network_conf.h,
src/network/bridge_driver.c: Convert to use virSocketAddr
in virNetwork, instead of char *.
* src/util/bridge.c, src/util/bridge.h,
src/util/dnsmasq.c, src/util/dnsmasq.h,
src/util/iptables.c, src/util/iptables.h: Convert to
take a virSocketAddr instead of char * for any IP
address parameters
* src/util/network.h: Add macros to determine if an address
is set, and what address family is set.
2010-10-21 12:14:33 +00:00
|
|
|
}
|
2009-09-21 20:50:25 +00:00
|
|
|
}
|
|
|
|
|
2010-12-10 18:54:48 +00:00
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(bridgeaddr);
|
|
|
|
return ret;
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2010-12-10 21:04:37 +00:00
|
|
|
networkStartDhcpDaemon(virNetworkObjPtr network)
|
2008-10-10 13:57:13 +00:00
|
|
|
{
|
2010-12-10 18:54:48 +00:00
|
|
|
virCommandPtr cmd = NULL;
|
|
|
|
char *pidfile = NULL;
|
2010-12-10 21:04:37 +00:00
|
|
|
int ret = -1, err, ii;
|
|
|
|
virNetworkIpDefPtr ipdef;
|
2009-01-20 22:36:10 +00:00
|
|
|
|
|
|
|
network->dnsmasqPid = -1;
|
2008-10-10 13:57:13 +00:00
|
|
|
|
2010-12-10 21:04:37 +00:00
|
|
|
/* Look for first IPv4 address that has dhcp defined. */
|
|
|
|
/* We support dhcp config on 1 IPv4 interface only. */
|
|
|
|
for (ii = 0;
|
|
|
|
(ipdef = virNetworkDefGetIpByIndex(network->def, AF_INET, ii));
|
|
|
|
ii++) {
|
|
|
|
if (ipdef->nranges || ipdef->nhosts)
|
|
|
|
break;
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
2010-12-10 21:04:37 +00:00
|
|
|
if (!ipdef)
|
|
|
|
return 0;
|
2008-10-10 13:57:13 +00:00
|
|
|
|
2010-01-20 23:52:13 +00:00
|
|
|
if ((err = virFileMakePath(NETWORK_PID_DIR)) != 0) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(err,
|
2009-01-20 22:36:10 +00:00
|
|
|
_("cannot create directory %s"),
|
|
|
|
NETWORK_PID_DIR);
|
2010-12-10 18:54:48 +00:00
|
|
|
goto cleanup;
|
2009-01-20 22:36:10 +00:00
|
|
|
}
|
2010-01-20 23:52:13 +00:00
|
|
|
if ((err = virFileMakePath(NETWORK_STATE_DIR)) != 0) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(err,
|
2009-01-20 22:36:10 +00:00
|
|
|
_("cannot create directory %s"),
|
|
|
|
NETWORK_STATE_DIR);
|
2010-12-10 18:54:48 +00:00
|
|
|
goto cleanup;
|
2009-01-20 22:36:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!(pidfile = virFilePid(NETWORK_PID_DIR, network->def->name))) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2010-12-10 18:54:48 +00:00
|
|
|
goto cleanup;
|
2009-01-20 22:36:10 +00:00
|
|
|
}
|
|
|
|
|
2010-12-10 18:54:48 +00:00
|
|
|
cmd = virCommandNew(DNSMASQ);
|
2010-11-17 18:36:19 +00:00
|
|
|
if (networkBuildDnsmasqArgv(network, ipdef, pidfile, cmd) < 0) {
|
2010-12-10 18:54:48 +00:00
|
|
|
goto cleanup;
|
2009-01-20 22:36:10 +00:00
|
|
|
}
|
|
|
|
|
2010-12-10 18:54:48 +00:00
|
|
|
if (virCommandRun(cmd, NULL) < 0)
|
2009-01-20 22:36:10 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/*
|
2010-12-10 18:54:48 +00:00
|
|
|
* There really is no race here - when dnsmasq daemonizes, its
|
|
|
|
* leader process stays around until its child has actually
|
|
|
|
* written its pidfile. So by time virCommandRun exits it has
|
|
|
|
* waitpid'd and guaranteed the proess has started and written a
|
|
|
|
* pid
|
2009-01-20 22:36:10 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
if (virFileReadPid(NETWORK_PID_DIR, network->def->name,
|
|
|
|
&network->dnsmasqPid) < 0)
|
|
|
|
goto cleanup;
|
2008-10-10 13:57:13 +00:00
|
|
|
|
2009-01-20 22:36:10 +00:00
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(pidfile);
|
2010-12-10 18:54:48 +00:00
|
|
|
virCommandFree(cmd);
|
2008-10-10 13:57:13 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2010-12-20 06:14:11 +00:00
|
|
|
static int
|
|
|
|
networkStartRadvd(virNetworkObjPtr network)
|
|
|
|
{
|
|
|
|
char *pidfile = NULL;
|
|
|
|
char *radvdpidbase = NULL;
|
|
|
|
virBuffer configbuf = VIR_BUFFER_INITIALIZER;;
|
|
|
|
char *configstr = NULL;
|
|
|
|
char *configfile = NULL;
|
|
|
|
virCommandPtr cmd = NULL;
|
|
|
|
int ret = -1, err, ii;
|
|
|
|
virNetworkIpDefPtr ipdef;
|
|
|
|
|
|
|
|
network->radvdPid = -1;
|
|
|
|
|
|
|
|
if ((err = virFileMakePath(NETWORK_PID_DIR)) != 0) {
|
|
|
|
virReportSystemError(err,
|
|
|
|
_("cannot create directory %s"),
|
|
|
|
NETWORK_PID_DIR);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
if ((err = virFileMakePath(RADVD_STATE_DIR)) != 0) {
|
|
|
|
virReportSystemError(err,
|
|
|
|
_("cannot create directory %s"),
|
|
|
|
RADVD_STATE_DIR);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* construct pidfile name */
|
|
|
|
if (!(radvdpidbase = networkRadvdPidfileBasename(network->def->name))) {
|
|
|
|
virReportOOMError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
if (!(pidfile = virFilePid(NETWORK_PID_DIR, radvdpidbase))) {
|
|
|
|
virReportOOMError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* create radvd config file appropriate for this network */
|
|
|
|
virBufferVSprintf(&configbuf, "interface %s\n"
|
|
|
|
"{\n"
|
|
|
|
" AdvSendAdvert on;\n"
|
|
|
|
" AdvManagedFlag off;\n"
|
|
|
|
" AdvOtherConfigFlag off;\n"
|
|
|
|
"\n",
|
|
|
|
network->def->bridge);
|
|
|
|
for (ii = 0;
|
|
|
|
(ipdef = virNetworkDefGetIpByIndex(network->def, AF_INET6, ii));
|
|
|
|
ii++) {
|
|
|
|
int prefix;
|
|
|
|
char *netaddr;
|
|
|
|
|
|
|
|
prefix = virNetworkIpDefPrefix(ipdef);
|
|
|
|
if (prefix < 0) {
|
|
|
|
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("bridge '%s' has an invalid prefix"),
|
|
|
|
network->def->bridge);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
if (!(netaddr = virSocketFormatAddr(&ipdef->address)))
|
|
|
|
goto cleanup;
|
|
|
|
virBufferVSprintf(&configbuf,
|
|
|
|
" prefix %s/%d\n"
|
|
|
|
" {\n"
|
|
|
|
" AdvOnLink on;\n"
|
|
|
|
" AdvAutonomous on;\n"
|
|
|
|
" AdvRouterAddr off;\n"
|
|
|
|
" };\n",
|
|
|
|
netaddr, prefix);
|
|
|
|
VIR_FREE(netaddr);
|
|
|
|
}
|
|
|
|
|
|
|
|
virBufferAddLit(&configbuf, "};\n");
|
|
|
|
|
|
|
|
if (virBufferError(&configbuf)) {
|
|
|
|
virReportOOMError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
if (!(configstr = virBufferContentAndReset(&configbuf))) {
|
|
|
|
virReportOOMError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* construct the filename */
|
|
|
|
if (!(configfile = networkRadvdConfigFileName(network->def->name))) {
|
|
|
|
virReportOOMError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
/* write the file */
|
|
|
|
if (virFileWriteStr(configfile, configstr, 0600) < 0) {
|
|
|
|
virReportSystemError(errno,
|
|
|
|
_("couldn't write radvd config file '%s'"),
|
|
|
|
configfile);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* prevent radvd from daemonizing itself with "--debug 1", and use
|
|
|
|
* a dummy pidfile name - virCommand will create the pidfile we
|
|
|
|
* want to use (this is necessary because radvd's internal
|
|
|
|
* daemonization and pidfile creation causes a race, and the
|
|
|
|
* virFileReadPid() below will fail if we use them).
|
|
|
|
* Unfortunately, it isn't possible to tell radvd to not create
|
|
|
|
* its own pidfile, so we just let it do so, with a slightly
|
|
|
|
* different name. Unused, but harmless.
|
|
|
|
*/
|
|
|
|
cmd = virCommandNewArgList(RADVD, "--debug", "1",
|
|
|
|
"--config", configfile,
|
|
|
|
"--pidfile", NULL);
|
|
|
|
virCommandAddArgFormat(cmd, "%s-bin", pidfile);
|
|
|
|
|
|
|
|
virCommandSetPidFile(cmd, pidfile);
|
|
|
|
virCommandDaemonize(cmd);
|
|
|
|
|
|
|
|
if (virCommandRun(cmd, NULL) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virFileReadPid(NETWORK_PID_DIR, radvdpidbase,
|
|
|
|
&network->radvdPid) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
virCommandFree(cmd);
|
|
|
|
VIR_FREE(configfile);
|
|
|
|
VIR_FREE(configstr);
|
|
|
|
virBufferFreeAndReset(&configbuf);
|
|
|
|
VIR_FREE(radvdpidbase);
|
|
|
|
VIR_FREE(pidfile);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2008-10-10 13:57:13 +00:00
|
|
|
static int
|
2010-02-04 20:02:58 +00:00
|
|
|
networkAddMasqueradingIptablesRules(struct network_driver *driver,
|
2010-12-10 21:04:37 +00:00
|
|
|
virNetworkObjPtr network,
|
|
|
|
virNetworkIpDefPtr ipdef)
|
2010-11-17 18:36:19 +00:00
|
|
|
{
|
|
|
|
int prefix = virNetworkIpDefPrefix(ipdef);
|
2010-11-30 19:35:58 +00:00
|
|
|
|
|
|
|
if (prefix < 0) {
|
|
|
|
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Invalid prefix or netmask for '%s'"),
|
|
|
|
network->def->bridge);
|
|
|
|
goto masqerr1;
|
|
|
|
}
|
2010-12-14 20:01:10 +00:00
|
|
|
|
2008-10-10 13:57:13 +00:00
|
|
|
/* allow forwarding packets from the bridge interface */
|
2010-12-14 20:01:10 +00:00
|
|
|
if (iptablesAddForwardAllowOut(driver->iptables,
|
2010-11-17 18:36:19 +00:00
|
|
|
&ipdef->address,
|
2010-11-30 19:35:58 +00:00
|
|
|
prefix,
|
2010-12-14 20:01:10 +00:00
|
|
|
network->def->bridge,
|
|
|
|
network->def->forwardDev) < 0) {
|
|
|
|
networkReportError(VIR_ERR_SYSTEM_ERROR,
|
|
|
|
_("failed to add iptables rule to allow forwarding from '%s'"),
|
|
|
|
network->def->bridge);
|
2008-10-10 13:57:13 +00:00
|
|
|
goto masqerr1;
|
|
|
|
}
|
|
|
|
|
2010-12-10 21:04:37 +00:00
|
|
|
/* allow forwarding packets to the bridge interface if they are
|
|
|
|
* part of an existing connection
|
|
|
|
*/
|
2010-12-14 20:01:10 +00:00
|
|
|
if (iptablesAddForwardAllowRelatedIn(driver->iptables,
|
2010-11-17 18:36:19 +00:00
|
|
|
&ipdef->address,
|
2010-11-30 19:35:58 +00:00
|
|
|
prefix,
|
2010-12-14 20:01:10 +00:00
|
|
|
network->def->bridge,
|
|
|
|
network->def->forwardDev) < 0) {
|
|
|
|
networkReportError(VIR_ERR_SYSTEM_ERROR,
|
|
|
|
_("failed to add iptables rule to allow forwarding to '%s'"),
|
|
|
|
network->def->bridge);
|
2008-10-10 13:57:13 +00:00
|
|
|
goto masqerr2;
|
|
|
|
}
|
|
|
|
|
2010-06-10 16:50:38 +00:00
|
|
|
/*
|
|
|
|
* Enable masquerading.
|
|
|
|
*
|
|
|
|
* We need to end up with 3 rules in the table in this order
|
|
|
|
*
|
2010-07-28 14:05:55 +00:00
|
|
|
* 1. protocol=tcp with sport mapping restriction
|
|
|
|
* 2. protocol=udp with sport mapping restriction
|
2010-06-10 16:50:38 +00:00
|
|
|
* 3. generic any protocol
|
|
|
|
*
|
|
|
|
* The sport mappings are required, because default IPtables
|
2010-07-28 14:05:55 +00:00
|
|
|
* MASQUERADE maintain port numbers unchanged where possible.
|
2010-06-10 16:50:38 +00:00
|
|
|
*
|
|
|
|
* NFS can be configured to only "trust" port numbers < 1023.
|
|
|
|
*
|
|
|
|
* Guests using NAT thus need to be prevented from having port
|
|
|
|
* numbers < 1023, otherwise they can bypass the NFS "security"
|
|
|
|
* check on the source port number.
|
|
|
|
*
|
|
|
|
* Since we use '--insert' to add rules to the header of the
|
|
|
|
* chain, we actually need to add them in the reverse of the
|
|
|
|
* order just mentioned !
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* First the generic masquerade rule for other protocols */
|
2010-12-14 20:01:10 +00:00
|
|
|
if (iptablesAddForwardMasquerade(driver->iptables,
|
2010-11-17 18:36:19 +00:00
|
|
|
&ipdef->address,
|
2010-11-30 19:35:58 +00:00
|
|
|
prefix,
|
2010-12-14 20:01:10 +00:00
|
|
|
network->def->forwardDev,
|
|
|
|
NULL) < 0) {
|
|
|
|
networkReportError(VIR_ERR_SYSTEM_ERROR,
|
|
|
|
_("failed to add iptables rule to enable masquerading to '%s'"),
|
|
|
|
network->def->forwardDev ? network->def->forwardDev : NULL);
|
2008-10-10 13:57:13 +00:00
|
|
|
goto masqerr3;
|
|
|
|
}
|
|
|
|
|
2010-06-10 16:50:38 +00:00
|
|
|
/* UDP with a source port restriction */
|
2010-12-14 20:01:10 +00:00
|
|
|
if (iptablesAddForwardMasquerade(driver->iptables,
|
2010-11-17 18:36:19 +00:00
|
|
|
&ipdef->address,
|
2010-11-30 19:35:58 +00:00
|
|
|
prefix,
|
2010-12-14 20:01:10 +00:00
|
|
|
network->def->forwardDev,
|
|
|
|
"udp") < 0) {
|
|
|
|
networkReportError(VIR_ERR_SYSTEM_ERROR,
|
|
|
|
_("failed to add iptables rule to enable UDP masquerading to '%s'"),
|
|
|
|
network->def->forwardDev ? network->def->forwardDev : NULL);
|
2010-06-10 16:50:38 +00:00
|
|
|
goto masqerr4;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* TCP with a source port restriction */
|
2010-12-14 20:01:10 +00:00
|
|
|
if (iptablesAddForwardMasquerade(driver->iptables,
|
2010-11-17 18:36:19 +00:00
|
|
|
&ipdef->address,
|
2010-11-30 19:35:58 +00:00
|
|
|
prefix,
|
2010-12-14 20:01:10 +00:00
|
|
|
network->def->forwardDev,
|
|
|
|
"tcp") < 0) {
|
|
|
|
networkReportError(VIR_ERR_SYSTEM_ERROR,
|
|
|
|
_("failed to add iptables rule to enable TCP masquerading to '%s'"),
|
|
|
|
network->def->forwardDev ? network->def->forwardDev : NULL);
|
2010-06-10 16:50:38 +00:00
|
|
|
goto masqerr5;
|
|
|
|
}
|
|
|
|
|
2010-12-15 06:49:29 +00:00
|
|
|
return 0;
|
2008-10-10 13:57:13 +00:00
|
|
|
|
2010-06-10 16:50:38 +00:00
|
|
|
masqerr5:
|
|
|
|
iptablesRemoveForwardMasquerade(driver->iptables,
|
2010-11-17 18:36:19 +00:00
|
|
|
&ipdef->address,
|
2010-11-30 19:35:58 +00:00
|
|
|
prefix,
|
2010-06-10 16:50:38 +00:00
|
|
|
network->def->forwardDev,
|
|
|
|
"udp");
|
|
|
|
masqerr4:
|
|
|
|
iptablesRemoveForwardMasquerade(driver->iptables,
|
2010-11-17 18:36:19 +00:00
|
|
|
&ipdef->address,
|
2010-11-30 19:35:58 +00:00
|
|
|
prefix,
|
2010-06-10 16:50:38 +00:00
|
|
|
network->def->forwardDev,
|
|
|
|
NULL);
|
2008-10-10 13:57:13 +00:00
|
|
|
masqerr3:
|
|
|
|
iptablesRemoveForwardAllowRelatedIn(driver->iptables,
|
2010-11-17 18:36:19 +00:00
|
|
|
&ipdef->address,
|
2010-11-30 19:35:58 +00:00
|
|
|
prefix,
|
2010-10-25 14:10:33 +00:00
|
|
|
network->def->bridge,
|
|
|
|
network->def->forwardDev);
|
2008-10-10 13:57:13 +00:00
|
|
|
masqerr2:
|
|
|
|
iptablesRemoveForwardAllowOut(driver->iptables,
|
2010-11-17 18:36:19 +00:00
|
|
|
&ipdef->address,
|
2010-11-30 19:35:58 +00:00
|
|
|
prefix,
|
2008-10-10 13:57:13 +00:00
|
|
|
network->def->bridge,
|
|
|
|
network->def->forwardDev);
|
|
|
|
masqerr1:
|
2010-12-15 06:49:29 +00:00
|
|
|
return -1;
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
|
|
|
|
2010-12-10 21:04:37 +00:00
|
|
|
static void
|
|
|
|
networkRemoveMasqueradingIptablesRules(struct network_driver *driver,
|
|
|
|
virNetworkObjPtr network,
|
|
|
|
virNetworkIpDefPtr ipdef)
|
|
|
|
{
|
|
|
|
int prefix = virNetworkIpDefPrefix(ipdef);
|
|
|
|
|
|
|
|
if (prefix >= 0) {
|
|
|
|
iptablesRemoveForwardMasquerade(driver->iptables,
|
|
|
|
&ipdef->address,
|
|
|
|
prefix,
|
|
|
|
network->def->forwardDev,
|
|
|
|
"tcp");
|
|
|
|
iptablesRemoveForwardMasquerade(driver->iptables,
|
|
|
|
&ipdef->address,
|
|
|
|
prefix,
|
|
|
|
network->def->forwardDev,
|
|
|
|
"udp");
|
|
|
|
iptablesRemoveForwardMasquerade(driver->iptables,
|
|
|
|
&ipdef->address,
|
|
|
|
prefix,
|
|
|
|
network->def->forwardDev,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
iptablesRemoveForwardAllowRelatedIn(driver->iptables,
|
|
|
|
&ipdef->address,
|
|
|
|
prefix,
|
|
|
|
network->def->bridge,
|
|
|
|
network->def->forwardDev);
|
|
|
|
iptablesRemoveForwardAllowOut(driver->iptables,
|
|
|
|
&ipdef->address,
|
|
|
|
prefix,
|
|
|
|
network->def->bridge,
|
|
|
|
network->def->forwardDev);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-10-10 13:57:13 +00:00
|
|
|
static int
|
2010-02-04 20:02:58 +00:00
|
|
|
networkAddRoutingIptablesRules(struct network_driver *driver,
|
2010-11-17 18:36:19 +00:00
|
|
|
virNetworkObjPtr network,
|
2010-12-10 21:04:37 +00:00
|
|
|
virNetworkIpDefPtr ipdef)
|
|
|
|
{
|
2010-11-17 18:36:19 +00:00
|
|
|
int prefix = virNetworkIpDefPrefix(ipdef);
|
2010-11-30 19:35:58 +00:00
|
|
|
|
|
|
|
if (prefix < 0) {
|
|
|
|
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Invalid prefix or netmask for '%s'"),
|
|
|
|
network->def->bridge);
|
|
|
|
goto routeerr1;
|
|
|
|
}
|
2010-12-14 20:01:10 +00:00
|
|
|
|
2008-10-10 13:57:13 +00:00
|
|
|
/* allow routing packets from the bridge interface */
|
2010-12-14 20:01:10 +00:00
|
|
|
if (iptablesAddForwardAllowOut(driver->iptables,
|
2010-11-17 18:36:19 +00:00
|
|
|
&ipdef->address,
|
2010-11-30 19:35:58 +00:00
|
|
|
prefix,
|
2010-12-14 20:01:10 +00:00
|
|
|
network->def->bridge,
|
|
|
|
network->def->forwardDev) < 0) {
|
|
|
|
networkReportError(VIR_ERR_SYSTEM_ERROR,
|
|
|
|
_("failed to add iptables rule to allow routing from '%s'"),
|
|
|
|
network->def->bridge);
|
2008-10-10 13:57:13 +00:00
|
|
|
goto routeerr1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* allow routing packets to the bridge interface */
|
2010-12-14 20:01:10 +00:00
|
|
|
if (iptablesAddForwardAllowIn(driver->iptables,
|
2010-11-17 18:36:19 +00:00
|
|
|
&ipdef->address,
|
2010-11-30 19:35:58 +00:00
|
|
|
prefix,
|
2010-12-14 20:01:10 +00:00
|
|
|
network->def->bridge,
|
|
|
|
network->def->forwardDev) < 0) {
|
|
|
|
networkReportError(VIR_ERR_SYSTEM_ERROR,
|
|
|
|
_("failed to add iptables rule to allow routing to '%s'"),
|
|
|
|
network->def->bridge);
|
2008-10-10 13:57:13 +00:00
|
|
|
goto routeerr2;
|
|
|
|
}
|
|
|
|
|
2010-12-15 06:49:29 +00:00
|
|
|
return 0;
|
2008-10-10 13:57:13 +00:00
|
|
|
|
2010-12-10 21:04:37 +00:00
|
|
|
routeerr2:
|
2008-10-10 13:57:13 +00:00
|
|
|
iptablesRemoveForwardAllowOut(driver->iptables,
|
2010-11-17 18:36:19 +00:00
|
|
|
&ipdef->address,
|
2010-11-30 19:35:58 +00:00
|
|
|
prefix,
|
2008-10-10 13:57:13 +00:00
|
|
|
network->def->bridge,
|
|
|
|
network->def->forwardDev);
|
2010-12-10 21:04:37 +00:00
|
|
|
routeerr1:
|
2010-12-15 06:49:29 +00:00
|
|
|
return -1;
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
|
|
|
|
2010-12-10 21:04:37 +00:00
|
|
|
static void
|
|
|
|
networkRemoveRoutingIptablesRules(struct network_driver *driver,
|
|
|
|
virNetworkObjPtr network,
|
|
|
|
virNetworkIpDefPtr ipdef)
|
|
|
|
{
|
|
|
|
int prefix = virNetworkIpDefPrefix(ipdef);
|
|
|
|
|
|
|
|
if (prefix >= 0) {
|
|
|
|
iptablesRemoveForwardAllowIn(driver->iptables,
|
|
|
|
&ipdef->address,
|
|
|
|
prefix,
|
|
|
|
network->def->bridge,
|
|
|
|
network->def->forwardDev);
|
|
|
|
|
|
|
|
iptablesRemoveForwardAllowOut(driver->iptables,
|
|
|
|
&ipdef->address,
|
|
|
|
prefix,
|
|
|
|
network->def->bridge,
|
|
|
|
network->def->forwardDev);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-12-16 20:50:01 +00:00
|
|
|
/* Add all once/network rules required for IPv6 (if any IPv6 addresses are defined) */
|
|
|
|
static int
|
|
|
|
networkAddGeneralIp6tablesRules(struct network_driver *driver,
|
|
|
|
virNetworkObjPtr network)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (!virNetworkDefGetIpByIndex(network->def, AF_INET6, 0))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* Catch all rules to block forwarding to/from bridges */
|
|
|
|
|
|
|
|
if (iptablesAddForwardRejectOut(driver->iptables, AF_INET6,
|
|
|
|
network->def->bridge) < 0) {
|
|
|
|
networkReportError(VIR_ERR_SYSTEM_ERROR,
|
|
|
|
_("failed to add ip6tables rule to block outbound traffic from '%s'"),
|
|
|
|
network->def->bridge);
|
|
|
|
goto err1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (iptablesAddForwardRejectIn(driver->iptables, AF_INET6,
|
|
|
|
network->def->bridge) < 0) {
|
|
|
|
networkReportError(VIR_ERR_SYSTEM_ERROR,
|
|
|
|
_("failed to add ip6tables rule to block inbound traffic to '%s'"),
|
|
|
|
network->def->bridge);
|
|
|
|
goto err2;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Allow traffic between guests on the same bridge */
|
|
|
|
if (iptablesAddForwardAllowCross(driver->iptables, AF_INET6,
|
|
|
|
network->def->bridge) < 0) {
|
|
|
|
networkReportError(VIR_ERR_SYSTEM_ERROR,
|
|
|
|
_("failed to add ip6tables rule to allow cross bridge traffic on '%s'"),
|
|
|
|
network->def->bridge);
|
|
|
|
goto err3;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* unwind in reverse order from the point of failure */
|
|
|
|
err3:
|
|
|
|
iptablesRemoveForwardRejectIn(driver->iptables, AF_INET6, network->def->bridge);
|
|
|
|
err2:
|
|
|
|
iptablesRemoveForwardRejectOut(driver->iptables, AF_INET6, network->def->bridge);
|
|
|
|
err1:
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
networkRemoveGeneralIp6tablesRules(struct network_driver *driver,
|
|
|
|
virNetworkObjPtr network)
|
|
|
|
{
|
|
|
|
if (!virNetworkDefGetIpByIndex(network->def, AF_INET6, 0))
|
|
|
|
return;
|
|
|
|
|
|
|
|
iptablesRemoveForwardAllowCross(driver->iptables, AF_INET6, network->def->bridge);
|
|
|
|
iptablesRemoveForwardRejectIn(driver->iptables, AF_INET6, network->def->bridge);
|
|
|
|
iptablesRemoveForwardRejectOut(driver->iptables, AF_INET6, network->def->bridge);
|
|
|
|
}
|
|
|
|
|
2008-10-10 13:57:13 +00:00
|
|
|
static int
|
2010-12-10 21:04:37 +00:00
|
|
|
networkAddGeneralIptablesRules(struct network_driver *driver,
|
|
|
|
virNetworkObjPtr network)
|
|
|
|
{
|
|
|
|
int ii;
|
|
|
|
virNetworkIpDefPtr ipv4def;
|
|
|
|
|
|
|
|
/* First look for first IPv4 address that has dhcp or tftpboot defined. */
|
|
|
|
/* We support dhcp config on 1 IPv4 interface only. */
|
|
|
|
for (ii = 0;
|
|
|
|
(ipv4def = virNetworkDefGetIpByIndex(network->def, AF_INET, ii));
|
|
|
|
ii++) {
|
|
|
|
if (ipv4def->nranges || ipv4def->nhosts || ipv4def->tftproot)
|
|
|
|
break;
|
|
|
|
}
|
2008-10-10 13:57:13 +00:00
|
|
|
|
|
|
|
/* allow DHCP requests through to dnsmasq */
|
2010-12-10 21:04:37 +00:00
|
|
|
|
2010-12-08 19:09:25 +00:00
|
|
|
if (iptablesAddTcpInput(driver->iptables, AF_INET,
|
|
|
|
network->def->bridge, 67) < 0) {
|
2010-12-14 20:01:10 +00:00
|
|
|
networkReportError(VIR_ERR_SYSTEM_ERROR,
|
|
|
|
_("failed to add iptables rule to allow DHCP requests from '%s'"),
|
|
|
|
network->def->bridge);
|
2008-10-10 13:57:13 +00:00
|
|
|
goto err1;
|
|
|
|
}
|
|
|
|
|
2010-12-08 19:09:25 +00:00
|
|
|
if (iptablesAddUdpInput(driver->iptables, AF_INET,
|
|
|
|
network->def->bridge, 67) < 0) {
|
2010-12-14 20:01:10 +00:00
|
|
|
networkReportError(VIR_ERR_SYSTEM_ERROR,
|
|
|
|
_("failed to add iptables rule to allow DHCP requests from '%s'"),
|
|
|
|
network->def->bridge);
|
2008-10-10 13:57:13 +00:00
|
|
|
goto err2;
|
|
|
|
}
|
|
|
|
|
2010-12-10 21:04:37 +00:00
|
|
|
/* If we are doing local DHCP service on this network, attempt to
|
|
|
|
* add a rule that will fixup the checksum of DHCP response
|
|
|
|
* packets back to the guests (but report failure without
|
|
|
|
* aborting, since not all iptables implementations support it).
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (ipv4def && (ipv4def->nranges || ipv4def->nhosts) &&
|
|
|
|
(iptablesAddOutputFixUdpChecksum(driver->iptables,
|
|
|
|
network->def->bridge, 68) < 0)) {
|
|
|
|
VIR_WARN("Could not add rule to fixup DHCP response checksums "
|
|
|
|
"on network '%s'.", network->def->name);
|
|
|
|
VIR_WARN0("May need to update iptables package & kernel to support CHECKSUM rule.");
|
|
|
|
}
|
|
|
|
|
2008-10-10 13:57:13 +00:00
|
|
|
/* allow DNS requests through to dnsmasq */
|
2010-12-08 19:09:25 +00:00
|
|
|
if (iptablesAddTcpInput(driver->iptables, AF_INET,
|
|
|
|
network->def->bridge, 53) < 0) {
|
2010-12-14 20:01:10 +00:00
|
|
|
networkReportError(VIR_ERR_SYSTEM_ERROR,
|
|
|
|
_("failed to add iptables rule to allow DNS requests from '%s'"),
|
|
|
|
network->def->bridge);
|
2008-10-10 13:57:13 +00:00
|
|
|
goto err3;
|
|
|
|
}
|
|
|
|
|
2010-12-08 19:09:25 +00:00
|
|
|
if (iptablesAddUdpInput(driver->iptables, AF_INET,
|
|
|
|
network->def->bridge, 53) < 0) {
|
2010-12-14 20:01:10 +00:00
|
|
|
networkReportError(VIR_ERR_SYSTEM_ERROR,
|
|
|
|
_("failed to add iptables rule to allow DNS requests from '%s'"),
|
|
|
|
network->def->bridge);
|
2008-10-10 13:57:13 +00:00
|
|
|
goto err4;
|
|
|
|
}
|
|
|
|
|
2010-12-10 21:04:37 +00:00
|
|
|
/* allow TFTP requests through to dnsmasq if necessary */
|
|
|
|
if (ipv4def && ipv4def->tftproot &&
|
2010-12-08 19:09:25 +00:00
|
|
|
iptablesAddUdpInput(driver->iptables, AF_INET,
|
|
|
|
network->def->bridge, 69) < 0) {
|
2010-12-14 20:01:10 +00:00
|
|
|
networkReportError(VIR_ERR_SYSTEM_ERROR,
|
|
|
|
_("failed to add iptables rule to allow TFTP requests from '%s'"),
|
|
|
|
network->def->bridge);
|
2010-12-10 21:04:37 +00:00
|
|
|
goto err5;
|
2010-06-19 18:08:26 +00:00
|
|
|
}
|
|
|
|
|
2008-10-10 13:57:13 +00:00
|
|
|
/* Catch all rules to block forwarding to/from bridges */
|
|
|
|
|
2010-12-08 19:09:25 +00:00
|
|
|
if (iptablesAddForwardRejectOut(driver->iptables, AF_INET,
|
|
|
|
network->def->bridge) < 0) {
|
2010-12-14 20:01:10 +00:00
|
|
|
networkReportError(VIR_ERR_SYSTEM_ERROR,
|
|
|
|
_("failed to add iptables rule to block outbound traffic from '%s'"),
|
|
|
|
network->def->bridge);
|
2010-12-10 21:04:37 +00:00
|
|
|
goto err6;
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
|
|
|
|
2010-12-08 19:09:25 +00:00
|
|
|
if (iptablesAddForwardRejectIn(driver->iptables, AF_INET,
|
|
|
|
network->def->bridge) < 0) {
|
2010-12-14 20:01:10 +00:00
|
|
|
networkReportError(VIR_ERR_SYSTEM_ERROR,
|
|
|
|
_("failed to add iptables rule to block inbound traffic to '%s'"),
|
|
|
|
network->def->bridge);
|
2010-12-10 21:04:37 +00:00
|
|
|
goto err7;
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Allow traffic between guests on the same bridge */
|
2010-12-08 19:09:25 +00:00
|
|
|
if (iptablesAddForwardAllowCross(driver->iptables, AF_INET,
|
|
|
|
network->def->bridge) < 0) {
|
2010-12-14 20:01:10 +00:00
|
|
|
networkReportError(VIR_ERR_SYSTEM_ERROR,
|
|
|
|
_("failed to add iptables rule to allow cross bridge traffic on '%s'"),
|
|
|
|
network->def->bridge);
|
2010-12-10 21:04:37 +00:00
|
|
|
goto err8;
|
2010-07-13 02:59:58 +00:00
|
|
|
}
|
|
|
|
|
2010-12-16 20:50:01 +00:00
|
|
|
/* add IPv6 general rules, if needed */
|
|
|
|
if (networkAddGeneralIp6tablesRules(driver, network) < 0) {
|
|
|
|
goto err9;
|
|
|
|
}
|
|
|
|
|
2010-12-15 06:49:29 +00:00
|
|
|
return 0;
|
2008-10-10 13:57:13 +00:00
|
|
|
|
2010-12-10 21:04:37 +00:00
|
|
|
/* unwind in reverse order from the point of failure */
|
2010-12-16 20:50:01 +00:00
|
|
|
err9:
|
|
|
|
iptablesRemoveForwardAllowCross(driver->iptables, AF_INET, network->def->bridge);
|
2010-12-10 21:04:37 +00:00
|
|
|
err8:
|
2010-12-08 19:09:25 +00:00
|
|
|
iptablesRemoveForwardRejectIn(driver->iptables, AF_INET, network->def->bridge);
|
2010-12-10 21:04:37 +00:00
|
|
|
err7:
|
2010-12-08 19:09:25 +00:00
|
|
|
iptablesRemoveForwardRejectOut(driver->iptables, AF_INET, network->def->bridge);
|
2010-12-10 21:04:37 +00:00
|
|
|
err6:
|
|
|
|
if (ipv4def && ipv4def->tftproot) {
|
2010-12-08 19:09:25 +00:00
|
|
|
iptablesRemoveUdpInput(driver->iptables, AF_INET, network->def->bridge, 69);
|
2010-06-19 18:08:26 +00:00
|
|
|
}
|
2010-12-10 21:04:37 +00:00
|
|
|
err5:
|
2010-12-08 19:09:25 +00:00
|
|
|
iptablesRemoveUdpInput(driver->iptables, AF_INET, network->def->bridge, 53);
|
2010-12-10 21:04:37 +00:00
|
|
|
err4:
|
2010-12-08 19:09:25 +00:00
|
|
|
iptablesRemoveTcpInput(driver->iptables, AF_INET, network->def->bridge, 53);
|
2010-12-10 21:04:37 +00:00
|
|
|
err3:
|
2010-12-08 19:09:25 +00:00
|
|
|
iptablesRemoveUdpInput(driver->iptables, AF_INET, network->def->bridge, 67);
|
2010-12-10 21:04:37 +00:00
|
|
|
err2:
|
2010-12-08 19:09:25 +00:00
|
|
|
iptablesRemoveTcpInput(driver->iptables, AF_INET, network->def->bridge, 67);
|
2010-12-10 21:04:37 +00:00
|
|
|
err1:
|
2010-12-15 06:49:29 +00:00
|
|
|
return -1;
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2010-12-10 21:04:37 +00:00
|
|
|
networkRemoveGeneralIptablesRules(struct network_driver *driver,
|
|
|
|
virNetworkObjPtr network)
|
|
|
|
{
|
|
|
|
int ii;
|
|
|
|
virNetworkIpDefPtr ipv4def;
|
2010-11-17 18:36:19 +00:00
|
|
|
|
2010-12-16 20:50:01 +00:00
|
|
|
networkRemoveGeneralIp6tablesRules(driver, network);
|
|
|
|
|
2010-12-10 21:04:37 +00:00
|
|
|
for (ii = 0;
|
|
|
|
(ipv4def = virNetworkDefGetIpByIndex(network->def, AF_INET, ii));
|
|
|
|
ii++) {
|
|
|
|
if (ipv4def->nranges || ipv4def->nhosts || ipv4def->tftproot)
|
|
|
|
break;
|
2010-07-13 02:59:58 +00:00
|
|
|
}
|
2010-11-30 19:35:58 +00:00
|
|
|
|
2010-12-08 19:09:25 +00:00
|
|
|
iptablesRemoveForwardAllowCross(driver->iptables, AF_INET, network->def->bridge);
|
|
|
|
iptablesRemoveForwardRejectIn(driver->iptables, AF_INET, network->def->bridge);
|
|
|
|
iptablesRemoveForwardRejectOut(driver->iptables, AF_INET, network->def->bridge);
|
2010-12-10 21:04:37 +00:00
|
|
|
if (ipv4def && ipv4def->tftproot) {
|
2010-12-08 19:09:25 +00:00
|
|
|
iptablesRemoveUdpInput(driver->iptables, AF_INET, network->def->bridge, 69);
|
2010-12-10 21:04:37 +00:00
|
|
|
}
|
2010-12-08 19:09:25 +00:00
|
|
|
iptablesRemoveUdpInput(driver->iptables, AF_INET, network->def->bridge, 53);
|
|
|
|
iptablesRemoveTcpInput(driver->iptables, AF_INET, network->def->bridge, 53);
|
2010-12-10 21:04:37 +00:00
|
|
|
if (ipv4def && (ipv4def->nranges || ipv4def->nhosts)) {
|
|
|
|
iptablesRemoveOutputFixUdpChecksum(driver->iptables,
|
|
|
|
network->def->bridge, 68);
|
|
|
|
}
|
2010-12-08 19:09:25 +00:00
|
|
|
iptablesRemoveUdpInput(driver->iptables, AF_INET, network->def->bridge, 67);
|
|
|
|
iptablesRemoveTcpInput(driver->iptables, AF_INET, network->def->bridge, 67);
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
|
|
|
|
2010-12-10 21:04:37 +00:00
|
|
|
static int
|
|
|
|
networkAddIpSpecificIptablesRules(struct network_driver *driver,
|
|
|
|
virNetworkObjPtr network,
|
|
|
|
virNetworkIpDefPtr ipdef)
|
|
|
|
{
|
2010-12-16 20:50:01 +00:00
|
|
|
/* NB: in the case of IPv6, routing rules are added when the
|
|
|
|
* forward mode is NAT. This is because IPv6 has no NAT.
|
|
|
|
*/
|
2010-12-10 21:04:37 +00:00
|
|
|
|
2010-12-16 20:50:01 +00:00
|
|
|
if (network->def->forwardType == VIR_NETWORK_FORWARD_NAT) {
|
|
|
|
if (VIR_SOCKET_IS_FAMILY(&ipdef->address, AF_INET))
|
|
|
|
return networkAddMasqueradingIptablesRules(driver, network, ipdef);
|
|
|
|
else if (VIR_SOCKET_IS_FAMILY(&ipdef->address, AF_INET6))
|
|
|
|
return networkAddRoutingIptablesRules(driver, network, ipdef);
|
|
|
|
} else if (network->def->forwardType == VIR_NETWORK_FORWARD_ROUTE) {
|
|
|
|
return networkAddRoutingIptablesRules(driver, network, ipdef);
|
|
|
|
}
|
2010-12-10 21:04:37 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
networkRemoveIpSpecificIptablesRules(struct network_driver *driver,
|
|
|
|
virNetworkObjPtr network,
|
|
|
|
virNetworkIpDefPtr ipdef)
|
|
|
|
{
|
2010-12-16 20:50:01 +00:00
|
|
|
if (network->def->forwardType == VIR_NETWORK_FORWARD_NAT) {
|
|
|
|
if (VIR_SOCKET_IS_FAMILY(&ipdef->address, AF_INET))
|
|
|
|
networkRemoveMasqueradingIptablesRules(driver, network, ipdef);
|
|
|
|
else if (VIR_SOCKET_IS_FAMILY(&ipdef->address, AF_INET6))
|
|
|
|
networkRemoveRoutingIptablesRules(driver, network, ipdef);
|
|
|
|
} else if (network->def->forwardType == VIR_NETWORK_FORWARD_ROUTE) {
|
2010-12-10 21:04:37 +00:00
|
|
|
networkRemoveRoutingIptablesRules(driver, network, ipdef);
|
2010-12-16 20:50:01 +00:00
|
|
|
}
|
2010-12-10 21:04:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Add all rules for all ip addresses (and general rules) on a network */
|
|
|
|
static int
|
|
|
|
networkAddIptablesRules(struct network_driver *driver,
|
|
|
|
virNetworkObjPtr network)
|
|
|
|
{
|
|
|
|
int ii;
|
|
|
|
virNetworkIpDefPtr ipdef;
|
|
|
|
|
|
|
|
/* Add "once per network" rules */
|
|
|
|
if (networkAddGeneralIptablesRules(driver, network) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
for (ii = 0;
|
|
|
|
(ipdef = virNetworkDefGetIpByIndex(network->def, AF_UNSPEC, ii));
|
|
|
|
ii++) {
|
|
|
|
/* Add address-specific iptables rules */
|
|
|
|
if (networkAddIpSpecificIptablesRules(driver, network, ipdef) < 0) {
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
err:
|
|
|
|
/* The final failed call to networkAddIpSpecificIptablesRules will
|
|
|
|
* have removed any rules it created, but we need to remove those
|
|
|
|
* added for previous IP addresses.
|
|
|
|
*/
|
|
|
|
while ((--ii >= 0) &&
|
|
|
|
(ipdef = virNetworkDefGetIpByIndex(network->def, AF_UNSPEC, ii))) {
|
|
|
|
networkRemoveIpSpecificIptablesRules(driver, network, ipdef);
|
|
|
|
}
|
|
|
|
networkRemoveGeneralIptablesRules(driver, network);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Remove all rules for all ip addresses (and general rules) on a network */
|
|
|
|
static void
|
|
|
|
networkRemoveIptablesRules(struct network_driver *driver,
|
|
|
|
virNetworkObjPtr network)
|
|
|
|
{
|
|
|
|
int ii;
|
|
|
|
virNetworkIpDefPtr ipdef;
|
|
|
|
|
|
|
|
for (ii = 0;
|
|
|
|
(ipdef = virNetworkDefGetIpByIndex(network->def, AF_UNSPEC, ii));
|
|
|
|
ii++) {
|
|
|
|
networkRemoveIpSpecificIptablesRules(driver, network, ipdef);
|
|
|
|
}
|
|
|
|
networkRemoveGeneralIptablesRules(driver, network);
|
|
|
|
}
|
|
|
|
|
2009-12-10 11:27:17 +00:00
|
|
|
static void
|
|
|
|
networkReloadIptablesRules(struct network_driver *driver)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
VIR_INFO0(_("Reloading iptables rules"));
|
|
|
|
|
|
|
|
for (i = 0 ; i < driver->networks.count ; i++) {
|
|
|
|
virNetworkObjLock(driver->networks.objs[i]);
|
|
|
|
if (virNetworkObjIsActive(driver->networks.objs[i])) {
|
2010-12-10 21:04:37 +00:00
|
|
|
networkRemoveIptablesRules(driver, driver->networks.objs[i]);
|
|
|
|
if (networkAddIptablesRules(driver, driver->networks.objs[i]) < 0) {
|
|
|
|
/* failed to add but already logged */
|
|
|
|
}
|
2009-12-10 11:27:17 +00:00
|
|
|
}
|
|
|
|
virNetworkObjUnlock(driver->networks.objs[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-02-22 11:19:54 +00:00
|
|
|
/* Enable IP Forwarding. Return 0 for success, -1 for failure. */
|
2008-10-10 13:57:13 +00:00
|
|
|
static int
|
2010-12-20 06:14:11 +00:00
|
|
|
networkEnableIpForwarding(bool enableIPv4, bool enableIPv6)
|
2008-10-10 13:57:13 +00:00
|
|
|
{
|
2010-12-20 06:14:11 +00:00
|
|
|
int ret = 0;
|
|
|
|
if (enableIPv4)
|
|
|
|
ret = virFileWriteStr("/proc/sys/net/ipv4/ip_forward", "1\n", 0);
|
|
|
|
if (enableIPv6 && ret == 0)
|
|
|
|
ret = virFileWriteStr("/proc/sys/net/ipv6/conf/all/forwarding", "1\n", 0);
|
|
|
|
return ret;
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
|
|
|
|
2009-07-30 15:34:56 +00:00
|
|
|
#define SYSCTL_PATH "/proc/sys"
|
|
|
|
|
2010-12-16 20:50:01 +00:00
|
|
|
static int
|
|
|
|
networkSetIPv6Sysctls(virNetworkObjPtr network)
|
2009-07-30 15:34:56 +00:00
|
|
|
{
|
|
|
|
char *field = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
2010-12-16 20:50:01 +00:00
|
|
|
if (!virNetworkDefGetIpByIndex(network->def, AF_INET6, 0)) {
|
|
|
|
/* Only set disable_ipv6 if there are no ipv6 addresses defined for
|
|
|
|
* the network.
|
|
|
|
*/
|
|
|
|
if (virAsprintf(&field, SYSCTL_PATH "/net/ipv6/conf/%s/disable_ipv6",
|
|
|
|
network->def->bridge) < 0) {
|
|
|
|
virReportOOMError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2009-07-30 15:34:56 +00:00
|
|
|
|
2010-12-16 20:50:01 +00:00
|
|
|
if (access(field, W_OK) < 0 && errno == ENOENT) {
|
|
|
|
VIR_DEBUG("ipv6 appears to already be disabled on %s",
|
|
|
|
network->def->bridge);
|
|
|
|
ret = 0;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2009-08-10 10:16:37 +00:00
|
|
|
|
2010-12-16 20:50:01 +00:00
|
|
|
if (virFileWriteStr(field, "1", 0) < 0) {
|
|
|
|
virReportSystemError(errno,
|
|
|
|
_("cannot write to %s to disable IPv6 on bridge %s"),
|
|
|
|
field, network->def->bridge);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
VIR_FREE(field);
|
2009-07-30 15:34:56 +00:00
|
|
|
}
|
|
|
|
|
2010-12-16 20:50:01 +00:00
|
|
|
/* The rest of the ipv6 sysctl tunables should always be set,
|
|
|
|
* whether or not we're using ipv6 on this bridge.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Prevent guests from hijacking the host network by sending out
|
|
|
|
* their own router advertisements.
|
|
|
|
*/
|
|
|
|
if (virAsprintf(&field, SYSCTL_PATH "/net/ipv6/conf/%s/accept_ra",
|
|
|
|
network->def->bridge) < 0) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2009-07-30 15:34:56 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2010-12-03 09:47:08 +00:00
|
|
|
if (virFileWriteStr(field, "0", 0) < 0) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2009-07-30 15:34:56 +00:00
|
|
|
_("cannot disable %s"), field);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
VIR_FREE(field);
|
|
|
|
|
2010-12-16 20:50:01 +00:00
|
|
|
/* All interfaces used as a gateway (which is what this is, by
|
|
|
|
* definition), must always have autoconf=0.
|
|
|
|
*/
|
|
|
|
if (virAsprintf(&field, SYSCTL_PATH "/net/ipv6/conf/%s/autoconf",
|
|
|
|
network->def->bridge) < 0) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2009-07-30 15:34:56 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2010-12-03 09:47:08 +00:00
|
|
|
if (virFileWriteStr(field, "1", 0) < 0) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2009-07-30 15:34:56 +00:00
|
|
|
_("cannot enable %s"), field);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(field);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2010-05-20 23:31:16 +00:00
|
|
|
#define PROC_NET_ROUTE "/proc/net/route"
|
|
|
|
|
|
|
|
/* XXX: This function can be a lot more exhaustive, there are certainly
|
|
|
|
* other scenarios where we can ruin host network connectivity.
|
|
|
|
* XXX: Using a proper library is preferred over parsing /proc
|
|
|
|
*/
|
2010-12-10 21:04:37 +00:00
|
|
|
static int
|
|
|
|
networkCheckRouteCollision(virNetworkObjPtr network)
|
2010-05-20 23:31:16 +00:00
|
|
|
{
|
2010-12-10 21:04:37 +00:00
|
|
|
int ret = 0, len;
|
2010-05-20 23:31:16 +00:00
|
|
|
char *cur, *buf = NULL;
|
|
|
|
enum {MAX_ROUTE_SIZE = 1024*64};
|
|
|
|
|
|
|
|
/* Read whole routing table into memory */
|
|
|
|
if ((len = virFileReadAll(PROC_NET_ROUTE, MAX_ROUTE_SIZE, &buf)) < 0)
|
2010-12-10 21:04:37 +00:00
|
|
|
goto out;
|
2010-05-20 23:31:16 +00:00
|
|
|
|
|
|
|
/* Dropping the last character shouldn't hurt */
|
|
|
|
if (len > 0)
|
|
|
|
buf[len-1] = '\0';
|
|
|
|
|
|
|
|
VIR_DEBUG("%s output:\n%s", PROC_NET_ROUTE, buf);
|
|
|
|
|
|
|
|
if (!STRPREFIX (buf, "Iface"))
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
/* First line is just headings, skip it */
|
|
|
|
cur = strchr(buf, '\n');
|
|
|
|
if (cur)
|
|
|
|
cur++;
|
|
|
|
|
|
|
|
while (cur) {
|
|
|
|
char iface[17], dest[128], mask[128];
|
|
|
|
unsigned int addr_val, mask_val;
|
2010-12-10 21:04:37 +00:00
|
|
|
virNetworkIpDefPtr ipdef;
|
|
|
|
int num, ii;
|
2010-05-20 23:31:16 +00:00
|
|
|
|
|
|
|
/* NUL-terminate the line, so sscanf doesn't go beyond a newline. */
|
|
|
|
char *nl = strchr(cur, '\n');
|
|
|
|
if (nl) {
|
|
|
|
*nl++ = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
num = sscanf(cur, "%16s %127s %*s %*s %*s %*s %*s %127s",
|
|
|
|
iface, dest, mask);
|
|
|
|
cur = nl;
|
|
|
|
|
|
|
|
if (num != 3) {
|
|
|
|
VIR_DEBUG("Failed to parse %s", PROC_NET_ROUTE);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virStrToLong_ui(dest, NULL, 16, &addr_val) < 0) {
|
|
|
|
VIR_DEBUG("Failed to convert network address %s to uint", dest);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virStrToLong_ui(mask, NULL, 16, &mask_val) < 0) {
|
|
|
|
VIR_DEBUG("Failed to convert network mask %s to uint", mask);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
addr_val &= mask_val;
|
|
|
|
|
2010-12-10 21:04:37 +00:00
|
|
|
for (ii = 0;
|
|
|
|
(ipdef = virNetworkDefGetIpByIndex(network->def, AF_INET, ii));
|
|
|
|
ii++) {
|
|
|
|
|
|
|
|
unsigned int net_dest;
|
|
|
|
virSocketAddr netmask;
|
|
|
|
|
|
|
|
if (virNetworkIpDefNetmask(ipdef, &netmask) < 0) {
|
|
|
|
VIR_WARN("Failed to get netmask of '%s'",
|
|
|
|
network->def->bridge);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
net_dest = (ipdef->address.data.inet4.sin_addr.s_addr &
|
|
|
|
netmask.data.inet4.sin_addr.s_addr);
|
|
|
|
|
|
|
|
if ((net_dest == addr_val) &&
|
|
|
|
(netmask.data.inet4.sin_addr.s_addr == mask_val)) {
|
|
|
|
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Network is already in use by interface %s"),
|
|
|
|
iface);
|
|
|
|
ret = -1;
|
|
|
|
goto out;
|
|
|
|
}
|
2010-05-20 23:31:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
out:
|
|
|
|
VIR_FREE(buf);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2010-12-10 21:04:37 +00:00
|
|
|
static int
|
|
|
|
networkAddAddrToBridge(struct network_driver *driver,
|
|
|
|
virNetworkObjPtr network,
|
|
|
|
virNetworkIpDefPtr ipdef)
|
2010-02-10 10:22:52 +00:00
|
|
|
{
|
2010-12-10 21:04:37 +00:00
|
|
|
int prefix = virNetworkIpDefPrefix(ipdef);
|
|
|
|
|
|
|
|
if (prefix < 0) {
|
|
|
|
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("bridge '%s' has an invalid netmask or IP address"),
|
|
|
|
network->def->bridge);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (brAddInetAddress(driver->brctl, network->def->bridge,
|
|
|
|
&ipdef->address, prefix) < 0) {
|
|
|
|
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("cannot set IP address on bridge '%s'"),
|
|
|
|
network->def->bridge);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
networkStartNetworkDaemon(struct network_driver *driver,
|
|
|
|
virNetworkObjPtr network)
|
|
|
|
{
|
|
|
|
int ii, err;
|
2010-12-16 20:50:01 +00:00
|
|
|
bool v4present = false, v6present = false;
|
2010-12-10 21:04:37 +00:00
|
|
|
virErrorPtr save_err = NULL;
|
|
|
|
virNetworkIpDefPtr ipdef;
|
2008-10-10 13:57:13 +00:00
|
|
|
|
Rename internal APis
Rename virDomainIsActive to virDomainObjIsActive, and
virInterfaceIsActive to virInterfaceObjIsActive and finally
virNetworkIsActive to virNetworkObjIsActive.
* src/conf/domain_conf.c, src/conf/domain_conf.h,
src/conf/interface_conf.h, src/conf/network_conf.c,
src/conf/network_conf.h, src/lxc/lxc_driver.c,
src/network/bridge_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_driver.c, src/qemu/qemu_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c: Update for
renamed APIs.
2009-10-20 14:51:03 +00:00
|
|
|
if (virNetworkObjIsActive(network)) {
|
2010-02-10 10:22:52 +00:00
|
|
|
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("network is already active"));
|
2008-10-10 13:57:13 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2010-12-10 21:04:37 +00:00
|
|
|
/* Check to see if any network IP collides with an existing route */
|
|
|
|
if (networkCheckRouteCollision(network) < 0)
|
2010-05-20 23:31:16 +00:00
|
|
|
return -1;
|
|
|
|
|
2010-12-10 21:04:37 +00:00
|
|
|
/* Create and configure the bridge device */
|
2009-03-02 17:37:03 +00:00
|
|
|
if ((err = brAddBridge(driver->brctl, network->def->bridge))) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(err,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("cannot create bridge '%s'"),
|
|
|
|
network->def->bridge);
|
2008-10-10 13:57:13 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2010-12-10 21:04:37 +00:00
|
|
|
/* Set bridge options */
|
2010-12-14 17:14:39 +00:00
|
|
|
if ((err = brSetForwardDelay(driver->brctl, network->def->bridge,
|
|
|
|
network->def->delay))) {
|
|
|
|
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("cannot set forward delay on bridge '%s'"),
|
|
|
|
network->def->bridge);
|
2010-12-10 21:04:37 +00:00
|
|
|
goto err1;
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
|
|
|
|
2010-12-14 17:14:39 +00:00
|
|
|
if ((err = brSetEnableSTP(driver->brctl, network->def->bridge,
|
|
|
|
network->def->stp ? 1 : 0))) {
|
2010-11-30 19:35:58 +00:00
|
|
|
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
2010-12-14 17:14:39 +00:00
|
|
|
_("cannot set STP '%s' on bridge '%s'"),
|
|
|
|
network->def->stp ? "on" : "off", network->def->bridge);
|
2010-12-10 21:04:37 +00:00
|
|
|
goto err1;
|
2010-11-30 19:35:58 +00:00
|
|
|
}
|
|
|
|
|
2010-12-16 20:50:01 +00:00
|
|
|
/* Disable IPv6 on the bridge if there are no IPv6 addresses
|
|
|
|
* defined, and set other IPv6 sysctl tunables appropriately.
|
|
|
|
*/
|
|
|
|
if (networkSetIPv6Sysctls(network) < 0)
|
2010-12-10 21:04:37 +00:00
|
|
|
goto err1;
|
2010-12-14 17:14:39 +00:00
|
|
|
|
2010-12-10 21:04:37 +00:00
|
|
|
/* Add "once per network" rules */
|
|
|
|
if (networkAddIptablesRules(driver, network) < 0)
|
|
|
|
goto err1;
|
|
|
|
|
|
|
|
for (ii = 0;
|
|
|
|
(ipdef = virNetworkDefGetIpByIndex(network->def, AF_UNSPEC, ii));
|
|
|
|
ii++) {
|
|
|
|
if (VIR_SOCKET_IS_FAMILY(&ipdef->address, AF_INET))
|
|
|
|
v4present = true;
|
2010-12-16 20:50:01 +00:00
|
|
|
if (VIR_SOCKET_IS_FAMILY(&ipdef->address, AF_INET6))
|
|
|
|
v6present = true;
|
2010-12-14 17:14:39 +00:00
|
|
|
|
2010-12-10 21:04:37 +00:00
|
|
|
/* Add the IP address/netmask to the bridge */
|
|
|
|
if (networkAddAddrToBridge(driver, network, ipdef) < 0) {
|
|
|
|
goto err2;
|
2010-12-14 17:14:39 +00:00
|
|
|
}
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
|
|
|
|
2010-12-10 21:04:37 +00:00
|
|
|
/* Bring up the bridge interface */
|
2009-05-12 15:31:22 +00:00
|
|
|
if ((err = brSetInterfaceUp(driver->brctl, network->def->bridge, 1))) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(err,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("failed to bring the bridge '%s' up"),
|
|
|
|
network->def->bridge);
|
2010-12-10 21:04:37 +00:00
|
|
|
goto err2;
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
|
|
|
|
2010-12-10 21:04:37 +00:00
|
|
|
/* If forwardType != NONE, turn on global IP forwarding */
|
2008-10-10 13:57:13 +00:00
|
|
|
if (network->def->forwardType != VIR_NETWORK_FORWARD_NONE &&
|
2010-12-20 06:14:11 +00:00
|
|
|
networkEnableIpForwarding(v4present, v6present) < 0) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno, "%s",
|
2009-01-20 17:13:33 +00:00
|
|
|
_("failed to enable IP forwarding"));
|
2010-12-10 21:04:37 +00:00
|
|
|
goto err3;
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
|
|
|
|
2010-12-10 21:04:37 +00:00
|
|
|
|
|
|
|
/* start dnsmasq if there are any IPv4 addresses */
|
|
|
|
if (v4present && networkStartDhcpDaemon(network) < 0)
|
|
|
|
goto err3;
|
2008-10-10 13:57:13 +00:00
|
|
|
|
2010-12-20 06:14:11 +00:00
|
|
|
/* start radvd if there are any ipv6 addresses */
|
|
|
|
if (v6present && networkStartRadvd(network) < 0)
|
|
|
|
goto err4;
|
|
|
|
|
2009-01-20 22:36:10 +00:00
|
|
|
/* Persist the live configuration now we have bridge info */
|
2010-02-10 10:22:52 +00:00
|
|
|
if (virNetworkSaveConfig(NETWORK_STATE_DIR, network->def) < 0) {
|
2010-12-20 06:14:11 +00:00
|
|
|
goto err5;
|
2009-01-20 22:36:10 +00:00
|
|
|
}
|
|
|
|
|
2008-10-10 13:57:13 +00:00
|
|
|
network->active = 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
2010-12-20 06:14:11 +00:00
|
|
|
err5:
|
|
|
|
if (!save_err)
|
|
|
|
save_err = virSaveLastError();
|
|
|
|
|
|
|
|
if (network->radvdPid > 0) {
|
|
|
|
kill(network->radvdPid, SIGTERM);
|
|
|
|
network->radvdPid = -1;
|
|
|
|
}
|
|
|
|
|
2010-12-10 21:04:37 +00:00
|
|
|
err4:
|
|
|
|
if (!save_err)
|
|
|
|
save_err = virSaveLastError();
|
|
|
|
|
2009-01-20 22:36:10 +00:00
|
|
|
if (network->dnsmasqPid > 0) {
|
|
|
|
kill(network->dnsmasqPid, SIGTERM);
|
|
|
|
network->dnsmasqPid = -1;
|
|
|
|
}
|
|
|
|
|
2010-12-10 21:04:37 +00:00
|
|
|
err3:
|
|
|
|
if (!save_err)
|
|
|
|
save_err = virSaveLastError();
|
2009-05-12 15:31:22 +00:00
|
|
|
if ((err = brSetInterfaceUp(driver->brctl, network->def->bridge, 0))) {
|
2009-02-05 16:28:30 +00:00
|
|
|
char ebuf[1024];
|
2010-05-19 10:00:18 +00:00
|
|
|
VIR_WARN("Failed to bring down bridge '%s' : %s",
|
2009-02-05 16:28:30 +00:00
|
|
|
network->def->bridge, virStrerror(err, ebuf, sizeof ebuf));
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
|
|
|
|
2010-12-10 21:04:37 +00:00
|
|
|
err2:
|
|
|
|
if (!save_err)
|
|
|
|
save_err = virSaveLastError();
|
|
|
|
networkRemoveIptablesRules(driver, network);
|
|
|
|
|
|
|
|
err1:
|
|
|
|
if (!save_err)
|
|
|
|
save_err = virSaveLastError();
|
2008-10-10 13:57:13 +00:00
|
|
|
if ((err = brDeleteBridge(driver->brctl, network->def->bridge))) {
|
2009-02-05 16:28:30 +00:00
|
|
|
char ebuf[1024];
|
2010-05-19 10:00:18 +00:00
|
|
|
VIR_WARN("Failed to delete bridge '%s' : %s",
|
2009-02-05 16:28:30 +00:00
|
|
|
network->def->bridge, virStrerror(err, ebuf, sizeof ebuf));
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
|
|
|
|
2010-12-10 21:04:37 +00:00
|
|
|
if (save_err) {
|
|
|
|
virSetError(save_err);
|
|
|
|
virFreeError(save_err);
|
|
|
|
}
|
2008-10-10 13:57:13 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
static int networkShutdownNetworkDaemon(struct network_driver *driver,
|
|
|
|
virNetworkObjPtr network)
|
|
|
|
{
|
2008-10-10 13:57:13 +00:00
|
|
|
int err;
|
2009-01-20 22:36:10 +00:00
|
|
|
char *stateFile;
|
2008-10-10 13:57:13 +00:00
|
|
|
|
2010-01-19 13:17:20 +00:00
|
|
|
VIR_INFO(_("Shutting down network '%s'"), network->def->name);
|
2008-10-10 13:57:13 +00:00
|
|
|
|
Rename internal APis
Rename virDomainIsActive to virDomainObjIsActive, and
virInterfaceIsActive to virInterfaceObjIsActive and finally
virNetworkIsActive to virNetworkObjIsActive.
* src/conf/domain_conf.c, src/conf/domain_conf.h,
src/conf/interface_conf.h, src/conf/network_conf.c,
src/conf/network_conf.h, src/lxc/lxc_driver.c,
src/network/bridge_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_driver.c, src/qemu/qemu_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c: Update for
renamed APIs.
2009-10-20 14:51:03 +00:00
|
|
|
if (!virNetworkObjIsActive(network))
|
2008-10-10 13:57:13 +00:00
|
|
|
return 0;
|
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
stateFile = virNetworkConfigFile(NETWORK_STATE_DIR, network->def->name);
|
2009-01-20 22:36:10 +00:00
|
|
|
if (!stateFile)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
unlink(stateFile);
|
|
|
|
VIR_FREE(stateFile);
|
|
|
|
|
2010-12-20 06:14:11 +00:00
|
|
|
if (network->radvdPid > 0) {
|
|
|
|
char *radvdpidbase;
|
|
|
|
|
|
|
|
kill(network->radvdPid, SIGTERM);
|
|
|
|
/* attempt to delete the pidfile we created */
|
|
|
|
if (!(radvdpidbase = networkRadvdPidfileBasename(network->def->name))) {
|
|
|
|
virReportOOMError();
|
|
|
|
} else {
|
|
|
|
virFileDeletePid(NETWORK_PID_DIR, radvdpidbase);
|
|
|
|
VIR_FREE(radvdpidbase);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-10-10 13:57:13 +00:00
|
|
|
if (network->dnsmasqPid > 0)
|
|
|
|
kill(network->dnsmasqPid, SIGTERM);
|
|
|
|
|
2009-02-05 16:28:30 +00:00
|
|
|
char ebuf[1024];
|
2009-05-12 15:31:22 +00:00
|
|
|
if ((err = brSetInterfaceUp(driver->brctl, network->def->bridge, 0))) {
|
2010-05-19 10:00:18 +00:00
|
|
|
VIR_WARN("Failed to bring down bridge '%s' : %s",
|
2009-02-05 16:28:30 +00:00
|
|
|
network->def->bridge, virStrerror(err, ebuf, sizeof ebuf));
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
|
|
|
|
2010-12-10 21:04:37 +00:00
|
|
|
networkRemoveIptablesRules(driver, network);
|
|
|
|
|
2008-10-10 13:57:13 +00:00
|
|
|
if ((err = brDeleteBridge(driver->brctl, network->def->bridge))) {
|
2010-05-19 10:00:18 +00:00
|
|
|
VIR_WARN("Failed to delete bridge '%s' : %s",
|
2009-02-05 16:28:30 +00:00
|
|
|
network->def->bridge, virStrerror(err, ebuf, sizeof ebuf));
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
|
|
|
|
2009-01-20 22:36:10 +00:00
|
|
|
/* See if its still alive and really really kill it */
|
2008-10-10 13:57:13 +00:00
|
|
|
if (network->dnsmasqPid > 0 &&
|
2009-01-20 22:36:10 +00:00
|
|
|
(kill(network->dnsmasqPid, 0) == 0))
|
2008-10-10 13:57:13 +00:00
|
|
|
kill(network->dnsmasqPid, SIGKILL);
|
|
|
|
network->dnsmasqPid = -1;
|
2010-12-20 06:14:11 +00:00
|
|
|
|
|
|
|
if (network->radvdPid > 0 &&
|
|
|
|
(kill(network->radvdPid, 0) == 0))
|
|
|
|
kill(network->radvdPid, SIGKILL);
|
|
|
|
network->radvdPid = -1;
|
|
|
|
|
2008-10-10 13:57:13 +00:00
|
|
|
network->active = 0;
|
|
|
|
|
|
|
|
if (network->newDef) {
|
|
|
|
virNetworkDefFree(network->def);
|
|
|
|
network->def = network->newDef;
|
|
|
|
network->newDef = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-12-04 21:37:52 +00:00
|
|
|
static virNetworkPtr networkLookupByUUID(virConnectPtr conn,
|
|
|
|
const unsigned char *uuid) {
|
|
|
|
struct network_driver *driver = conn->networkPrivateData;
|
|
|
|
virNetworkObjPtr network;
|
|
|
|
virNetworkPtr ret = NULL;
|
2008-10-10 13:57:13 +00:00
|
|
|
|
2008-12-04 21:38:38 +00:00
|
|
|
networkDriverLock(driver);
|
2008-12-04 21:37:52 +00:00
|
|
|
network = virNetworkFindByUUID(&driver->networks, uuid);
|
2008-12-04 21:38:38 +00:00
|
|
|
networkDriverUnlock(driver);
|
2008-10-10 13:57:13 +00:00
|
|
|
if (!network) {
|
2010-02-10 10:22:52 +00:00
|
|
|
networkReportError(VIR_ERR_NO_NETWORK,
|
|
|
|
"%s", _("no network with matching uuid"));
|
2008-12-04 21:37:52 +00:00
|
|
|
goto cleanup;
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
|
|
|
|
2008-12-04 21:37:52 +00:00
|
|
|
ret = virGetNetwork(conn, network->def->name, network->def->uuid);
|
|
|
|
|
|
|
|
cleanup:
|
2008-12-04 21:38:38 +00:00
|
|
|
if (network)
|
|
|
|
virNetworkObjUnlock(network);
|
2008-12-04 21:37:52 +00:00
|
|
|
return ret;
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
|
|
|
|
2008-12-04 21:37:52 +00:00
|
|
|
static virNetworkPtr networkLookupByName(virConnectPtr conn,
|
|
|
|
const char *name) {
|
|
|
|
struct network_driver *driver = conn->networkPrivateData;
|
|
|
|
virNetworkObjPtr network;
|
|
|
|
virNetworkPtr ret = NULL;
|
|
|
|
|
2008-12-04 21:38:38 +00:00
|
|
|
networkDriverLock(driver);
|
2008-12-04 21:37:52 +00:00
|
|
|
network = virNetworkFindByName(&driver->networks, name);
|
2008-12-04 21:38:38 +00:00
|
|
|
networkDriverUnlock(driver);
|
2008-10-10 13:57:13 +00:00
|
|
|
if (!network) {
|
2010-02-10 10:22:52 +00:00
|
|
|
networkReportError(VIR_ERR_NO_NETWORK,
|
|
|
|
_("no network with matching name '%s'"), name);
|
2008-12-04 21:37:52 +00:00
|
|
|
goto cleanup;
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
|
|
|
|
2008-12-04 21:37:52 +00:00
|
|
|
ret = virGetNetwork(conn, network->def->name, network->def->uuid);
|
|
|
|
|
|
|
|
cleanup:
|
2008-12-04 21:38:38 +00:00
|
|
|
if (network)
|
|
|
|
virNetworkObjUnlock(network);
|
2008-12-04 21:37:52 +00:00
|
|
|
return ret;
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static virDrvOpenStatus networkOpenNetwork(virConnectPtr conn,
|
|
|
|
virConnectAuthPtr auth ATTRIBUTE_UNUSED,
|
|
|
|
int flags ATTRIBUTE_UNUSED) {
|
|
|
|
if (!driverState)
|
|
|
|
return VIR_DRV_OPEN_DECLINED;
|
|
|
|
|
|
|
|
conn->networkPrivateData = driverState;
|
|
|
|
return VIR_DRV_OPEN_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int networkCloseNetwork(virConnectPtr conn) {
|
|
|
|
conn->networkPrivateData = NULL;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int networkNumNetworks(virConnectPtr conn) {
|
2008-10-10 14:50:26 +00:00
|
|
|
int nactive = 0, i;
|
2008-12-04 21:37:52 +00:00
|
|
|
struct network_driver *driver = conn->networkPrivateData;
|
2008-10-10 14:50:26 +00:00
|
|
|
|
2008-12-04 21:38:38 +00:00
|
|
|
networkDriverLock(driver);
|
|
|
|
for (i = 0 ; i < driver->networks.count ; i++) {
|
|
|
|
virNetworkObjLock(driver->networks.objs[i]);
|
Rename internal APis
Rename virDomainIsActive to virDomainObjIsActive, and
virInterfaceIsActive to virInterfaceObjIsActive and finally
virNetworkIsActive to virNetworkObjIsActive.
* src/conf/domain_conf.c, src/conf/domain_conf.h,
src/conf/interface_conf.h, src/conf/network_conf.c,
src/conf/network_conf.h, src/lxc/lxc_driver.c,
src/network/bridge_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_driver.c, src/qemu/qemu_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c: Update for
renamed APIs.
2009-10-20 14:51:03 +00:00
|
|
|
if (virNetworkObjIsActive(driver->networks.objs[i]))
|
2008-10-10 13:57:13 +00:00
|
|
|
nactive++;
|
2008-12-04 21:38:38 +00:00
|
|
|
virNetworkObjUnlock(driver->networks.objs[i]);
|
|
|
|
}
|
|
|
|
networkDriverUnlock(driver);
|
2008-10-10 14:50:26 +00:00
|
|
|
|
2008-10-10 13:57:13 +00:00
|
|
|
return nactive;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int networkListNetworks(virConnectPtr conn, char **const names, int nnames) {
|
2008-12-04 21:37:52 +00:00
|
|
|
struct network_driver *driver = conn->networkPrivateData;
|
2008-10-10 13:57:13 +00:00
|
|
|
int got = 0, i;
|
2008-10-10 14:50:26 +00:00
|
|
|
|
2008-12-04 21:38:38 +00:00
|
|
|
networkDriverLock(driver);
|
2008-10-10 14:50:26 +00:00
|
|
|
for (i = 0 ; i < driver->networks.count && got < nnames ; i++) {
|
2008-12-04 21:38:38 +00:00
|
|
|
virNetworkObjLock(driver->networks.objs[i]);
|
Rename internal APis
Rename virDomainIsActive to virDomainObjIsActive, and
virInterfaceIsActive to virInterfaceObjIsActive and finally
virNetworkIsActive to virNetworkObjIsActive.
* src/conf/domain_conf.c, src/conf/domain_conf.h,
src/conf/interface_conf.h, src/conf/network_conf.c,
src/conf/network_conf.h, src/lxc/lxc_driver.c,
src/network/bridge_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_driver.c, src/qemu/qemu_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c: Update for
renamed APIs.
2009-10-20 14:51:03 +00:00
|
|
|
if (virNetworkObjIsActive(driver->networks.objs[i])) {
|
2008-10-10 14:50:26 +00:00
|
|
|
if (!(names[got] = strdup(driver->networks.objs[i]->def->name))) {
|
2008-12-04 21:38:38 +00:00
|
|
|
virNetworkObjUnlock(driver->networks.objs[i]);
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2008-10-10 13:57:13 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
got++;
|
|
|
|
}
|
2008-12-04 21:38:38 +00:00
|
|
|
virNetworkObjUnlock(driver->networks.objs[i]);
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
2008-12-04 21:38:38 +00:00
|
|
|
networkDriverUnlock(driver);
|
|
|
|
|
2008-10-10 13:57:13 +00:00
|
|
|
return got;
|
|
|
|
|
|
|
|
cleanup:
|
2008-12-04 21:38:38 +00:00
|
|
|
networkDriverUnlock(driver);
|
2008-10-10 13:57:13 +00:00
|
|
|
for (i = 0 ; i < got ; i++)
|
|
|
|
VIR_FREE(names[i]);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int networkNumDefinedNetworks(virConnectPtr conn) {
|
2008-10-10 14:50:26 +00:00
|
|
|
int ninactive = 0, i;
|
2008-12-04 21:37:52 +00:00
|
|
|
struct network_driver *driver = conn->networkPrivateData;
|
2008-10-10 14:50:26 +00:00
|
|
|
|
2008-12-04 21:38:38 +00:00
|
|
|
networkDriverLock(driver);
|
|
|
|
for (i = 0 ; i < driver->networks.count ; i++) {
|
|
|
|
virNetworkObjLock(driver->networks.objs[i]);
|
Rename internal APis
Rename virDomainIsActive to virDomainObjIsActive, and
virInterfaceIsActive to virInterfaceObjIsActive and finally
virNetworkIsActive to virNetworkObjIsActive.
* src/conf/domain_conf.c, src/conf/domain_conf.h,
src/conf/interface_conf.h, src/conf/network_conf.c,
src/conf/network_conf.h, src/lxc/lxc_driver.c,
src/network/bridge_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_driver.c, src/qemu/qemu_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c: Update for
renamed APIs.
2009-10-20 14:51:03 +00:00
|
|
|
if (!virNetworkObjIsActive(driver->networks.objs[i]))
|
2008-10-10 13:57:13 +00:00
|
|
|
ninactive++;
|
2008-12-04 21:38:38 +00:00
|
|
|
virNetworkObjUnlock(driver->networks.objs[i]);
|
|
|
|
}
|
|
|
|
networkDriverUnlock(driver);
|
2008-10-10 14:50:26 +00:00
|
|
|
|
2008-10-10 13:57:13 +00:00
|
|
|
return ninactive;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int networkListDefinedNetworks(virConnectPtr conn, char **const names, int nnames) {
|
2008-12-04 21:37:52 +00:00
|
|
|
struct network_driver *driver = conn->networkPrivateData;
|
2008-10-10 13:57:13 +00:00
|
|
|
int got = 0, i;
|
2008-10-10 14:50:26 +00:00
|
|
|
|
2008-12-04 21:38:38 +00:00
|
|
|
networkDriverLock(driver);
|
2008-10-10 14:50:26 +00:00
|
|
|
for (i = 0 ; i < driver->networks.count && got < nnames ; i++) {
|
2008-12-04 21:38:38 +00:00
|
|
|
virNetworkObjLock(driver->networks.objs[i]);
|
Rename internal APis
Rename virDomainIsActive to virDomainObjIsActive, and
virInterfaceIsActive to virInterfaceObjIsActive and finally
virNetworkIsActive to virNetworkObjIsActive.
* src/conf/domain_conf.c, src/conf/domain_conf.h,
src/conf/interface_conf.h, src/conf/network_conf.c,
src/conf/network_conf.h, src/lxc/lxc_driver.c,
src/network/bridge_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_driver.c, src/qemu/qemu_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c: Update for
renamed APIs.
2009-10-20 14:51:03 +00:00
|
|
|
if (!virNetworkObjIsActive(driver->networks.objs[i])) {
|
2008-10-10 14:50:26 +00:00
|
|
|
if (!(names[got] = strdup(driver->networks.objs[i]->def->name))) {
|
2008-12-04 21:38:38 +00:00
|
|
|
virNetworkObjUnlock(driver->networks.objs[i]);
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2008-10-10 13:57:13 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
got++;
|
|
|
|
}
|
2008-12-04 21:38:38 +00:00
|
|
|
virNetworkObjUnlock(driver->networks.objs[i]);
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
2008-12-04 21:38:38 +00:00
|
|
|
networkDriverUnlock(driver);
|
2008-10-10 13:57:13 +00:00
|
|
|
return got;
|
|
|
|
|
|
|
|
cleanup:
|
2008-12-04 21:38:38 +00:00
|
|
|
networkDriverUnlock(driver);
|
2008-10-10 13:57:13 +00:00
|
|
|
for (i = 0 ; i < got ; i++)
|
|
|
|
VIR_FREE(names[i]);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
Implmentation of new APIs to checking state/persistence of objects
This implements the virConnectIsSecure, virConnectIsEncrypted,
virDomainIsPersistent, virDomainIsActive, virNetworkIsActive,
virNetworkIsPersistent, virStoragePoolIsActive,
virStoragePoolIsPersistent, virInterfaceIsActive APIs in
(nearly) all drivers. Exceptions are:
phyp: missing domainIsActive/Persistent
esx: missing domainIsPersistent
opennebula: missing domainIsActive/Persistent
* src/remote/remote_protocol.x: Define remote wire ABI for newly
added APIs.
* daemon/remote_dispatch*.h: Re-generated from remote_protocol.x
* src/esx/esx_driver.c, src/lxc/lxc_driver.c, src/network/bridge_driver.c,
src/opennebula/one_driver.c, src/openvz/openvz_conf.c,
src/openvz/openvz_driver.c, src/phyp/phyp_driver.c,
src/remote/remote_driver.c, src/storage/storage_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c, src/vbox/vbox_tmpl.c,
src/xen/xen_driver.c, src/xen/xen_driver.h, src/xen/xen_inotify.c,
src/xen/xen_inotify.h: Implement all the new APIs where possible
2009-10-20 14:12:03 +00:00
|
|
|
|
|
|
|
static int networkIsActive(virNetworkPtr net)
|
|
|
|
{
|
2010-02-16 18:09:31 +00:00
|
|
|
struct network_driver *driver = net->conn->networkPrivateData;
|
Implmentation of new APIs to checking state/persistence of objects
This implements the virConnectIsSecure, virConnectIsEncrypted,
virDomainIsPersistent, virDomainIsActive, virNetworkIsActive,
virNetworkIsPersistent, virStoragePoolIsActive,
virStoragePoolIsPersistent, virInterfaceIsActive APIs in
(nearly) all drivers. Exceptions are:
phyp: missing domainIsActive/Persistent
esx: missing domainIsPersistent
opennebula: missing domainIsActive/Persistent
* src/remote/remote_protocol.x: Define remote wire ABI for newly
added APIs.
* daemon/remote_dispatch*.h: Re-generated from remote_protocol.x
* src/esx/esx_driver.c, src/lxc/lxc_driver.c, src/network/bridge_driver.c,
src/opennebula/one_driver.c, src/openvz/openvz_conf.c,
src/openvz/openvz_driver.c, src/phyp/phyp_driver.c,
src/remote/remote_driver.c, src/storage/storage_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c, src/vbox/vbox_tmpl.c,
src/xen/xen_driver.c, src/xen/xen_driver.h, src/xen/xen_inotify.c,
src/xen/xen_inotify.h: Implement all the new APIs where possible
2009-10-20 14:12:03 +00:00
|
|
|
virNetworkObjPtr obj;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
networkDriverLock(driver);
|
|
|
|
obj = virNetworkFindByUUID(&driver->networks, net->uuid);
|
|
|
|
networkDriverUnlock(driver);
|
|
|
|
if (!obj) {
|
2010-02-10 10:22:52 +00:00
|
|
|
networkReportError(VIR_ERR_NO_NETWORK, NULL);
|
Implmentation of new APIs to checking state/persistence of objects
This implements the virConnectIsSecure, virConnectIsEncrypted,
virDomainIsPersistent, virDomainIsActive, virNetworkIsActive,
virNetworkIsPersistent, virStoragePoolIsActive,
virStoragePoolIsPersistent, virInterfaceIsActive APIs in
(nearly) all drivers. Exceptions are:
phyp: missing domainIsActive/Persistent
esx: missing domainIsPersistent
opennebula: missing domainIsActive/Persistent
* src/remote/remote_protocol.x: Define remote wire ABI for newly
added APIs.
* daemon/remote_dispatch*.h: Re-generated from remote_protocol.x
* src/esx/esx_driver.c, src/lxc/lxc_driver.c, src/network/bridge_driver.c,
src/opennebula/one_driver.c, src/openvz/openvz_conf.c,
src/openvz/openvz_driver.c, src/phyp/phyp_driver.c,
src/remote/remote_driver.c, src/storage/storage_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c, src/vbox/vbox_tmpl.c,
src/xen/xen_driver.c, src/xen/xen_driver.h, src/xen/xen_inotify.c,
src/xen/xen_inotify.h: Implement all the new APIs where possible
2009-10-20 14:12:03 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
ret = virNetworkObjIsActive(obj);
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (obj)
|
|
|
|
virNetworkObjUnlock(obj);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int networkIsPersistent(virNetworkPtr net)
|
|
|
|
{
|
2010-02-16 18:09:31 +00:00
|
|
|
struct network_driver *driver = net->conn->networkPrivateData;
|
Implmentation of new APIs to checking state/persistence of objects
This implements the virConnectIsSecure, virConnectIsEncrypted,
virDomainIsPersistent, virDomainIsActive, virNetworkIsActive,
virNetworkIsPersistent, virStoragePoolIsActive,
virStoragePoolIsPersistent, virInterfaceIsActive APIs in
(nearly) all drivers. Exceptions are:
phyp: missing domainIsActive/Persistent
esx: missing domainIsPersistent
opennebula: missing domainIsActive/Persistent
* src/remote/remote_protocol.x: Define remote wire ABI for newly
added APIs.
* daemon/remote_dispatch*.h: Re-generated from remote_protocol.x
* src/esx/esx_driver.c, src/lxc/lxc_driver.c, src/network/bridge_driver.c,
src/opennebula/one_driver.c, src/openvz/openvz_conf.c,
src/openvz/openvz_driver.c, src/phyp/phyp_driver.c,
src/remote/remote_driver.c, src/storage/storage_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c, src/vbox/vbox_tmpl.c,
src/xen/xen_driver.c, src/xen/xen_driver.h, src/xen/xen_inotify.c,
src/xen/xen_inotify.h: Implement all the new APIs where possible
2009-10-20 14:12:03 +00:00
|
|
|
virNetworkObjPtr obj;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
networkDriverLock(driver);
|
|
|
|
obj = virNetworkFindByUUID(&driver->networks, net->uuid);
|
|
|
|
networkDriverUnlock(driver);
|
|
|
|
if (!obj) {
|
2010-02-10 10:22:52 +00:00
|
|
|
networkReportError(VIR_ERR_NO_NETWORK, NULL);
|
Implmentation of new APIs to checking state/persistence of objects
This implements the virConnectIsSecure, virConnectIsEncrypted,
virDomainIsPersistent, virDomainIsActive, virNetworkIsActive,
virNetworkIsPersistent, virStoragePoolIsActive,
virStoragePoolIsPersistent, virInterfaceIsActive APIs in
(nearly) all drivers. Exceptions are:
phyp: missing domainIsActive/Persistent
esx: missing domainIsPersistent
opennebula: missing domainIsActive/Persistent
* src/remote/remote_protocol.x: Define remote wire ABI for newly
added APIs.
* daemon/remote_dispatch*.h: Re-generated from remote_protocol.x
* src/esx/esx_driver.c, src/lxc/lxc_driver.c, src/network/bridge_driver.c,
src/opennebula/one_driver.c, src/openvz/openvz_conf.c,
src/openvz/openvz_driver.c, src/phyp/phyp_driver.c,
src/remote/remote_driver.c, src/storage/storage_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c, src/vbox/vbox_tmpl.c,
src/xen/xen_driver.c, src/xen/xen_driver.h, src/xen/xen_inotify.c,
src/xen/xen_inotify.h: Implement all the new APIs where possible
2009-10-20 14:12:03 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
ret = obj->persistent;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (obj)
|
|
|
|
virNetworkObjUnlock(obj);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-10 13:57:13 +00:00
|
|
|
static virNetworkPtr networkCreate(virConnectPtr conn, const char *xml) {
|
2008-12-04 21:37:52 +00:00
|
|
|
struct network_driver *driver = conn->networkPrivateData;
|
2008-10-10 13:57:13 +00:00
|
|
|
virNetworkDefPtr def;
|
2008-12-04 21:38:38 +00:00
|
|
|
virNetworkObjPtr network = NULL;
|
2008-12-04 21:37:52 +00:00
|
|
|
virNetworkPtr ret = NULL;
|
2008-10-10 13:57:13 +00:00
|
|
|
|
2008-12-04 21:38:38 +00:00
|
|
|
networkDriverLock(driver);
|
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
if (!(def = virNetworkDefParseString(xml)))
|
2008-12-04 21:37:52 +00:00
|
|
|
goto cleanup;
|
2008-10-10 13:57:13 +00:00
|
|
|
|
2010-05-27 15:44:31 +00:00
|
|
|
if (virNetworkObjIsDuplicate(&driver->networks, def, 1) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
if (virNetworkSetBridgeName(&driver->networks, def, 1))
|
2009-03-02 17:37:03 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
if (!(network = virNetworkAssignDef(&driver->networks,
|
2008-12-04 21:37:52 +00:00
|
|
|
def)))
|
|
|
|
goto cleanup;
|
|
|
|
def = NULL;
|
2008-10-10 13:57:13 +00:00
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
if (networkStartNetworkDaemon(driver, network) < 0) {
|
2008-10-10 13:57:13 +00:00
|
|
|
virNetworkRemoveInactive(&driver->networks,
|
|
|
|
network);
|
2008-12-04 21:38:38 +00:00
|
|
|
network = NULL;
|
2008-12-04 21:37:52 +00:00
|
|
|
goto cleanup;
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
|
|
|
|
2008-12-04 21:37:52 +00:00
|
|
|
ret = virGetNetwork(conn, network->def->name, network->def->uuid);
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virNetworkDefFree(def);
|
2008-12-04 21:38:38 +00:00
|
|
|
if (network)
|
|
|
|
virNetworkObjUnlock(network);
|
|
|
|
networkDriverUnlock(driver);
|
2008-12-04 21:37:52 +00:00
|
|
|
return ret;
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static virNetworkPtr networkDefine(virConnectPtr conn, const char *xml) {
|
2008-12-04 21:37:52 +00:00
|
|
|
struct network_driver *driver = conn->networkPrivateData;
|
2010-12-10 21:04:37 +00:00
|
|
|
virNetworkIpDefPtr ipdef, ipv4def = NULL;
|
2008-10-10 13:57:13 +00:00
|
|
|
virNetworkDefPtr def;
|
2008-12-04 21:38:38 +00:00
|
|
|
virNetworkObjPtr network = NULL;
|
2008-12-04 21:37:52 +00:00
|
|
|
virNetworkPtr ret = NULL;
|
2010-12-10 21:04:37 +00:00
|
|
|
int ii;
|
2008-10-10 13:57:13 +00:00
|
|
|
|
2008-12-04 21:38:38 +00:00
|
|
|
networkDriverLock(driver);
|
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
if (!(def = virNetworkDefParseString(xml)))
|
2008-12-04 21:37:52 +00:00
|
|
|
goto cleanup;
|
2008-10-10 13:57:13 +00:00
|
|
|
|
2010-07-30 15:59:17 +00:00
|
|
|
if (virNetworkObjIsDuplicate(&driver->networks, def, 0) < 0)
|
2010-05-27 15:44:31 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
if (virNetworkSetBridgeName(&driver->networks, def, 1))
|
2009-03-02 17:37:03 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
if (!(network = virNetworkAssignDef(&driver->networks,
|
2008-12-04 21:37:52 +00:00
|
|
|
def)))
|
|
|
|
goto cleanup;
|
|
|
|
def = NULL;
|
2008-10-10 13:57:13 +00:00
|
|
|
|
2009-03-02 17:29:44 +00:00
|
|
|
network->persistent = 1;
|
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
if (virNetworkSaveConfig(driver->networkConfigDir,
|
2009-01-20 22:36:10 +00:00
|
|
|
network->newDef ? network->newDef : network->def) < 0) {
|
2008-10-10 13:57:13 +00:00
|
|
|
virNetworkRemoveInactive(&driver->networks,
|
|
|
|
network);
|
2008-12-04 21:38:38 +00:00
|
|
|
network = NULL;
|
2008-12-04 21:37:52 +00:00
|
|
|
goto cleanup;
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
|
|
|
|
2010-12-16 20:50:01 +00:00
|
|
|
/* We only support dhcp on one IPv4 address per defined network */
|
2010-12-10 21:04:37 +00:00
|
|
|
for (ii = 0;
|
|
|
|
(ipdef = virNetworkDefGetIpByIndex(network->def, AF_UNSPEC, ii));
|
|
|
|
ii++) {
|
|
|
|
if (VIR_SOCKET_IS_FAMILY(&ipdef->address, AF_INET)) {
|
|
|
|
if (ipdef->nranges || ipdef->nhosts) {
|
|
|
|
if (ipv4def) {
|
|
|
|
networkReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
"%s", _("Multiple dhcp sections found. dhcp is supported only for a single IPv4 address on each network"));
|
|
|
|
goto cleanup;
|
|
|
|
} else {
|
|
|
|
ipv4def = ipdef;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (ipv4def) {
|
2010-04-26 14:07:25 +00:00
|
|
|
dnsmasqContext *dctx = dnsmasqContextNew(network->def->name, DNSMASQ_STATE_DIR);
|
|
|
|
if (dctx == NULL)
|
|
|
|
goto cleanup;
|
|
|
|
|
2010-11-17 18:36:19 +00:00
|
|
|
networkSaveDnsmasqHostsfile(ipv4def, dctx, true);
|
2010-04-26 14:07:25 +00:00
|
|
|
dnsmasqContextFree(dctx);
|
|
|
|
}
|
|
|
|
|
2008-12-04 21:37:52 +00:00
|
|
|
ret = virGetNetwork(conn, network->def->name, network->def->uuid);
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virNetworkDefFree(def);
|
2008-12-04 21:38:38 +00:00
|
|
|
if (network)
|
|
|
|
virNetworkObjUnlock(network);
|
|
|
|
networkDriverUnlock(driver);
|
2008-12-04 21:37:52 +00:00
|
|
|
return ret;
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int networkUndefine(virNetworkPtr net) {
|
2008-12-04 21:37:52 +00:00
|
|
|
struct network_driver *driver = net->conn->networkPrivateData;
|
2010-11-17 18:36:19 +00:00
|
|
|
virNetworkObjPtr network;
|
2010-12-16 20:50:01 +00:00
|
|
|
virNetworkIpDefPtr ipdef;
|
|
|
|
bool dhcp_present = false, v6present = false;
|
2010-12-10 21:04:37 +00:00
|
|
|
int ret = -1, ii;
|
2008-10-10 13:57:13 +00:00
|
|
|
|
2008-12-04 21:38:38 +00:00
|
|
|
networkDriverLock(driver);
|
|
|
|
|
2008-12-04 21:37:52 +00:00
|
|
|
network = virNetworkFindByUUID(&driver->networks, net->uuid);
|
2008-10-10 13:57:13 +00:00
|
|
|
if (!network) {
|
2010-02-10 10:22:52 +00:00
|
|
|
networkReportError(VIR_ERR_INVALID_NETWORK,
|
2008-12-04 21:37:52 +00:00
|
|
|
"%s", _("no network with matching uuid"));
|
|
|
|
goto cleanup;
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
|
|
|
|
Rename internal APis
Rename virDomainIsActive to virDomainObjIsActive, and
virInterfaceIsActive to virInterfaceObjIsActive and finally
virNetworkIsActive to virNetworkObjIsActive.
* src/conf/domain_conf.c, src/conf/domain_conf.h,
src/conf/interface_conf.h, src/conf/network_conf.c,
src/conf/network_conf.h, src/lxc/lxc_driver.c,
src/network/bridge_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_driver.c, src/qemu/qemu_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c: Update for
renamed APIs.
2009-10-20 14:51:03 +00:00
|
|
|
if (virNetworkObjIsActive(network)) {
|
2010-02-10 10:22:52 +00:00
|
|
|
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
2008-12-04 21:37:52 +00:00
|
|
|
"%s", _("network is still active"));
|
|
|
|
goto cleanup;
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
if (virNetworkDeleteConfig(driver->networkConfigDir,
|
2009-01-20 22:36:10 +00:00
|
|
|
driver->networkAutostartDir,
|
|
|
|
network) < 0)
|
2008-12-04 21:37:52 +00:00
|
|
|
goto cleanup;
|
2008-10-10 13:57:13 +00:00
|
|
|
|
2010-12-10 21:04:37 +00:00
|
|
|
/* we only support dhcp on one IPv4 address per defined network */
|
|
|
|
for (ii = 0;
|
2010-12-16 20:50:01 +00:00
|
|
|
(ipdef = virNetworkDefGetIpByIndex(network->def, AF_UNSPEC, ii));
|
2010-12-10 21:04:37 +00:00
|
|
|
ii++) {
|
2010-12-16 20:50:01 +00:00
|
|
|
if (VIR_SOCKET_IS_FAMILY(&ipdef->address, AF_INET)) {
|
|
|
|
if (ipdef->nranges || ipdef->nhosts)
|
|
|
|
dhcp_present = true;
|
|
|
|
} else if (VIR_SOCKET_IS_FAMILY(&ipdef->address, AF_INET6)) {
|
|
|
|
v6present = true;
|
|
|
|
}
|
2010-12-10 21:04:37 +00:00
|
|
|
}
|
2010-12-16 20:50:01 +00:00
|
|
|
|
|
|
|
if (dhcp_present) {
|
2010-04-26 14:07:25 +00:00
|
|
|
dnsmasqContext *dctx = dnsmasqContextNew(network->def->name, DNSMASQ_STATE_DIR);
|
|
|
|
if (dctx == NULL)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
dnsmasqDelete(dctx);
|
|
|
|
dnsmasqContextFree(dctx);
|
|
|
|
}
|
|
|
|
|
2010-12-20 06:14:11 +00:00
|
|
|
if (v6present) {
|
|
|
|
char *configfile = networkRadvdConfigFileName(network->def->name);
|
|
|
|
|
|
|
|
if (!configfile) {
|
|
|
|
virReportOOMError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
unlink(configfile);
|
|
|
|
VIR_FREE(configfile);
|
|
|
|
|
|
|
|
char *radvdpidbase = networkRadvdPidfileBasename(network->def->name);
|
|
|
|
|
|
|
|
if (!(radvdpidbase)) {
|
|
|
|
virReportOOMError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
virFileDeletePid(NETWORK_PID_DIR, radvdpidbase);
|
|
|
|
VIR_FREE(radvdpidbase);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2008-10-10 13:57:13 +00:00
|
|
|
virNetworkRemoveInactive(&driver->networks,
|
|
|
|
network);
|
2008-12-04 21:38:38 +00:00
|
|
|
network = NULL;
|
2008-12-04 21:37:52 +00:00
|
|
|
ret = 0;
|
2008-10-10 13:57:13 +00:00
|
|
|
|
2008-12-04 21:37:52 +00:00
|
|
|
cleanup:
|
2008-12-04 21:38:38 +00:00
|
|
|
if (network)
|
|
|
|
virNetworkObjUnlock(network);
|
|
|
|
networkDriverUnlock(driver);
|
2008-12-04 21:37:52 +00:00
|
|
|
return ret;
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int networkStart(virNetworkPtr net) {
|
2008-12-04 21:37:52 +00:00
|
|
|
struct network_driver *driver = net->conn->networkPrivateData;
|
|
|
|
virNetworkObjPtr network;
|
|
|
|
int ret = -1;
|
2008-10-10 13:57:13 +00:00
|
|
|
|
2008-12-04 21:38:38 +00:00
|
|
|
networkDriverLock(driver);
|
2008-12-04 21:37:52 +00:00
|
|
|
network = virNetworkFindByUUID(&driver->networks, net->uuid);
|
2008-12-04 21:38:38 +00:00
|
|
|
|
2008-10-10 13:57:13 +00:00
|
|
|
if (!network) {
|
2010-02-10 10:22:52 +00:00
|
|
|
networkReportError(VIR_ERR_INVALID_NETWORK,
|
2008-12-04 21:37:52 +00:00
|
|
|
"%s", _("no network with matching uuid"));
|
|
|
|
goto cleanup;
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
ret = networkStartNetworkDaemon(driver, network);
|
2008-12-04 21:37:52 +00:00
|
|
|
|
|
|
|
cleanup:
|
2008-12-04 21:38:38 +00:00
|
|
|
if (network)
|
|
|
|
virNetworkObjUnlock(network);
|
2009-05-19 11:06:25 +00:00
|
|
|
networkDriverUnlock(driver);
|
2008-12-04 21:37:52 +00:00
|
|
|
return ret;
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int networkDestroy(virNetworkPtr net) {
|
2008-12-04 21:37:52 +00:00
|
|
|
struct network_driver *driver = net->conn->networkPrivateData;
|
|
|
|
virNetworkObjPtr network;
|
|
|
|
int ret = -1;
|
2008-10-10 13:57:13 +00:00
|
|
|
|
2008-12-04 21:38:38 +00:00
|
|
|
networkDriverLock(driver);
|
2008-12-04 21:37:52 +00:00
|
|
|
network = virNetworkFindByUUID(&driver->networks, net->uuid);
|
2008-12-04 21:38:38 +00:00
|
|
|
|
2008-10-10 13:57:13 +00:00
|
|
|
if (!network) {
|
2010-02-10 10:22:52 +00:00
|
|
|
networkReportError(VIR_ERR_INVALID_NETWORK,
|
2008-12-04 21:37:52 +00:00
|
|
|
"%s", _("no network with matching uuid"));
|
|
|
|
goto cleanup;
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
|
|
|
|
Rename internal APis
Rename virDomainIsActive to virDomainObjIsActive, and
virInterfaceIsActive to virInterfaceObjIsActive and finally
virNetworkIsActive to virNetworkObjIsActive.
* src/conf/domain_conf.c, src/conf/domain_conf.h,
src/conf/interface_conf.h, src/conf/network_conf.c,
src/conf/network_conf.h, src/lxc/lxc_driver.c,
src/network/bridge_driver.c, src/opennebula/one_driver.c,
src/openvz/openvz_driver.c, src/qemu/qemu_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c: Update for
renamed APIs.
2009-10-20 14:51:03 +00:00
|
|
|
if (!virNetworkObjIsActive(network)) {
|
2010-02-10 10:22:52 +00:00
|
|
|
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
2009-05-29 14:14:32 +00:00
|
|
|
"%s", _("network is not active"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
ret = networkShutdownNetworkDaemon(driver, network);
|
2009-01-20 22:36:10 +00:00
|
|
|
if (!network->persistent) {
|
2008-12-04 21:38:38 +00:00
|
|
|
virNetworkRemoveInactive(&driver->networks,
|
|
|
|
network);
|
|
|
|
network = NULL;
|
|
|
|
}
|
2008-10-10 13:57:13 +00:00
|
|
|
|
2008-12-04 21:37:52 +00:00
|
|
|
cleanup:
|
2008-12-04 21:38:38 +00:00
|
|
|
if (network)
|
|
|
|
virNetworkObjUnlock(network);
|
2009-05-19 11:06:25 +00:00
|
|
|
networkDriverUnlock(driver);
|
2008-10-10 13:57:13 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *networkDumpXML(virNetworkPtr net, int flags ATTRIBUTE_UNUSED) {
|
2008-12-04 21:37:52 +00:00
|
|
|
struct network_driver *driver = net->conn->networkPrivateData;
|
|
|
|
virNetworkObjPtr network;
|
|
|
|
char *ret = NULL;
|
2008-10-10 13:57:13 +00:00
|
|
|
|
2008-12-04 21:38:38 +00:00
|
|
|
networkDriverLock(driver);
|
2008-12-04 21:37:52 +00:00
|
|
|
network = virNetworkFindByUUID(&driver->networks, net->uuid);
|
2008-12-04 21:38:38 +00:00
|
|
|
networkDriverUnlock(driver);
|
|
|
|
|
2008-10-10 13:57:13 +00:00
|
|
|
if (!network) {
|
2010-02-10 10:22:52 +00:00
|
|
|
networkReportError(VIR_ERR_INVALID_NETWORK,
|
2008-12-04 21:37:52 +00:00
|
|
|
"%s", _("no network with matching uuid"));
|
|
|
|
goto cleanup;
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
ret = virNetworkDefFormat(network->def);
|
2008-12-04 21:37:52 +00:00
|
|
|
|
|
|
|
cleanup:
|
2008-12-04 21:38:38 +00:00
|
|
|
if (network)
|
|
|
|
virNetworkObjUnlock(network);
|
2008-12-04 21:37:52 +00:00
|
|
|
return ret;
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static char *networkGetBridgeName(virNetworkPtr net) {
|
2008-12-04 21:37:52 +00:00
|
|
|
struct network_driver *driver = net->conn->networkPrivateData;
|
|
|
|
virNetworkObjPtr network;
|
|
|
|
char *bridge = NULL;
|
|
|
|
|
2008-12-04 21:38:38 +00:00
|
|
|
networkDriverLock(driver);
|
2008-12-04 21:37:52 +00:00
|
|
|
network = virNetworkFindByUUID(&driver->networks, net->uuid);
|
2008-12-04 21:38:38 +00:00
|
|
|
networkDriverUnlock(driver);
|
|
|
|
|
2008-10-10 13:57:13 +00:00
|
|
|
if (!network) {
|
2010-02-10 10:22:52 +00:00
|
|
|
networkReportError(VIR_ERR_INVALID_NETWORK,
|
2008-12-04 21:37:52 +00:00
|
|
|
"%s", _("no network with matching id"));
|
|
|
|
goto cleanup;
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
|
|
|
|
2008-12-11 14:57:45 +00:00
|
|
|
if (!(network->def->bridge)) {
|
2010-02-10 10:22:52 +00:00
|
|
|
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
2008-12-11 14:57:45 +00:00
|
|
|
_("network '%s' does not have a bridge name."),
|
|
|
|
network->def->name);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2008-10-10 13:57:13 +00:00
|
|
|
bridge = strdup(network->def->bridge);
|
2008-12-04 21:37:52 +00:00
|
|
|
if (!bridge)
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2008-12-04 21:37:52 +00:00
|
|
|
|
|
|
|
cleanup:
|
2008-12-04 21:38:38 +00:00
|
|
|
if (network)
|
|
|
|
virNetworkObjUnlock(network);
|
2008-10-10 13:57:13 +00:00
|
|
|
return bridge;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int networkGetAutostart(virNetworkPtr net,
|
|
|
|
int *autostart) {
|
2008-12-04 21:37:52 +00:00
|
|
|
struct network_driver *driver = net->conn->networkPrivateData;
|
|
|
|
virNetworkObjPtr network;
|
|
|
|
int ret = -1;
|
2008-10-10 13:57:13 +00:00
|
|
|
|
2008-12-04 21:38:38 +00:00
|
|
|
networkDriverLock(driver);
|
2008-12-04 21:37:52 +00:00
|
|
|
network = virNetworkFindByUUID(&driver->networks, net->uuid);
|
2008-12-04 21:38:38 +00:00
|
|
|
networkDriverUnlock(driver);
|
2008-10-10 13:57:13 +00:00
|
|
|
if (!network) {
|
2010-02-10 10:22:52 +00:00
|
|
|
networkReportError(VIR_ERR_INVALID_NETWORK,
|
|
|
|
"%s", _("no network with matching uuid"));
|
2008-12-04 21:37:52 +00:00
|
|
|
goto cleanup;
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
*autostart = network->autostart;
|
2008-12-04 21:37:52 +00:00
|
|
|
ret = 0;
|
2008-10-10 13:57:13 +00:00
|
|
|
|
2008-12-04 21:37:52 +00:00
|
|
|
cleanup:
|
2008-12-04 21:38:38 +00:00
|
|
|
if (network)
|
|
|
|
virNetworkObjUnlock(network);
|
2008-12-04 21:37:52 +00:00
|
|
|
return ret;
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int networkSetAutostart(virNetworkPtr net,
|
2009-01-20 22:36:10 +00:00
|
|
|
int autostart) {
|
2008-12-04 21:37:52 +00:00
|
|
|
struct network_driver *driver = net->conn->networkPrivateData;
|
|
|
|
virNetworkObjPtr network;
|
2009-01-20 22:36:10 +00:00
|
|
|
char *configFile = NULL, *autostartLink = NULL;
|
2008-12-04 21:37:52 +00:00
|
|
|
int ret = -1;
|
2008-10-10 13:57:13 +00:00
|
|
|
|
2008-12-04 21:38:38 +00:00
|
|
|
networkDriverLock(driver);
|
2008-12-04 21:37:52 +00:00
|
|
|
network = virNetworkFindByUUID(&driver->networks, net->uuid);
|
2008-12-04 21:38:38 +00:00
|
|
|
|
2008-10-10 13:57:13 +00:00
|
|
|
if (!network) {
|
2010-02-10 10:22:52 +00:00
|
|
|
networkReportError(VIR_ERR_INVALID_NETWORK,
|
|
|
|
"%s", _("no network with matching uuid"));
|
2008-12-04 21:37:52 +00:00
|
|
|
goto cleanup;
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
|
|
|
|
2009-06-03 13:52:06 +00:00
|
|
|
if (!network->persistent) {
|
2010-02-10 10:22:52 +00:00
|
|
|
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("cannot set autostart for transient network"));
|
2009-06-03 13:52:06 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2008-10-10 13:57:13 +00:00
|
|
|
autostart = (autostart != 0);
|
|
|
|
|
2008-12-04 21:37:52 +00:00
|
|
|
if (network->autostart != autostart) {
|
2010-02-10 10:22:52 +00:00
|
|
|
if ((configFile = virNetworkConfigFile(driver->networkConfigDir, network->def->name)) == NULL)
|
2009-01-20 22:36:10 +00:00
|
|
|
goto cleanup;
|
2010-02-10 10:22:52 +00:00
|
|
|
if ((autostartLink = virNetworkConfigFile(driver->networkAutostartDir, network->def->name)) == NULL)
|
2009-01-20 22:36:10 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2008-12-04 21:37:52 +00:00
|
|
|
if (autostart) {
|
2009-09-04 17:37:37 +00:00
|
|
|
if (virFileMakePath(driver->networkAutostartDir)) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("cannot create autostart directory '%s'"),
|
|
|
|
driver->networkAutostartDir);
|
2008-12-04 21:37:52 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2008-10-10 13:57:13 +00:00
|
|
|
|
2009-01-20 22:36:10 +00:00
|
|
|
if (symlink(configFile, autostartLink) < 0) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("Failed to create symlink '%s' to '%s'"),
|
2009-01-20 22:36:10 +00:00
|
|
|
autostartLink, configFile);
|
2008-12-04 21:37:52 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
} else {
|
2009-01-20 22:36:10 +00:00
|
|
|
if (unlink(autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("Failed to delete symlink '%s'"),
|
2009-01-20 22:36:10 +00:00
|
|
|
autostartLink);
|
2008-12-04 21:37:52 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
|
|
|
|
2008-12-04 21:37:52 +00:00
|
|
|
network->autostart = autostart;
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
2008-12-04 21:37:52 +00:00
|
|
|
ret = 0;
|
2008-10-10 13:57:13 +00:00
|
|
|
|
2008-12-04 21:37:52 +00:00
|
|
|
cleanup:
|
2009-01-20 22:36:10 +00:00
|
|
|
VIR_FREE(configFile);
|
|
|
|
VIR_FREE(autostartLink);
|
2008-12-04 21:38:38 +00:00
|
|
|
if (network)
|
|
|
|
virNetworkObjUnlock(network);
|
2009-05-19 11:06:25 +00:00
|
|
|
networkDriverUnlock(driver);
|
2008-12-04 21:37:52 +00:00
|
|
|
return ret;
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static virNetworkDriver networkDriver = {
|
|
|
|
"Network",
|
|
|
|
networkOpenNetwork, /* open */
|
|
|
|
networkCloseNetwork, /* close */
|
|
|
|
networkNumNetworks, /* numOfNetworks */
|
|
|
|
networkListNetworks, /* listNetworks */
|
|
|
|
networkNumDefinedNetworks, /* numOfDefinedNetworks */
|
|
|
|
networkListDefinedNetworks, /* listDefinedNetworks */
|
|
|
|
networkLookupByUUID, /* networkLookupByUUID */
|
|
|
|
networkLookupByName, /* networkLookupByName */
|
|
|
|
networkCreate, /* networkCreateXML */
|
|
|
|
networkDefine, /* networkDefineXML */
|
|
|
|
networkUndefine, /* networkUndefine */
|
|
|
|
networkStart, /* networkCreate */
|
|
|
|
networkDestroy, /* networkDestroy */
|
|
|
|
networkDumpXML, /* networkDumpXML */
|
|
|
|
networkGetBridgeName, /* networkGetBridgeName */
|
|
|
|
networkGetAutostart, /* networkGetAutostart */
|
|
|
|
networkSetAutostart, /* networkSetAutostart */
|
Implmentation of new APIs to checking state/persistence of objects
This implements the virConnectIsSecure, virConnectIsEncrypted,
virDomainIsPersistent, virDomainIsActive, virNetworkIsActive,
virNetworkIsPersistent, virStoragePoolIsActive,
virStoragePoolIsPersistent, virInterfaceIsActive APIs in
(nearly) all drivers. Exceptions are:
phyp: missing domainIsActive/Persistent
esx: missing domainIsPersistent
opennebula: missing domainIsActive/Persistent
* src/remote/remote_protocol.x: Define remote wire ABI for newly
added APIs.
* daemon/remote_dispatch*.h: Re-generated from remote_protocol.x
* src/esx/esx_driver.c, src/lxc/lxc_driver.c, src/network/bridge_driver.c,
src/opennebula/one_driver.c, src/openvz/openvz_conf.c,
src/openvz/openvz_driver.c, src/phyp/phyp_driver.c,
src/remote/remote_driver.c, src/storage/storage_driver.c,
src/test/test_driver.c, src/uml/uml_driver.c, src/vbox/vbox_tmpl.c,
src/xen/xen_driver.c, src/xen/xen_driver.h, src/xen/xen_inotify.c,
src/xen/xen_inotify.h: Implement all the new APIs where possible
2009-10-20 14:12:03 +00:00
|
|
|
networkIsActive,
|
|
|
|
networkIsPersistent,
|
2008-10-10 13:57:13 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static virStateDriver networkStateDriver = {
|
Fix return value in virStateInitialize impl for LXC
The LXC driver was mistakenly returning -1 for lxcStartup()
in scenarios that are not an error. This caused the libvirtd
to quit for unprivileged users. This fixes the return code
of LXC driver, and also adds a "name" field to the virStateDriver
struct and logging to make it easier to find these problems
in the future
* src/driver.h: Add a 'name' field to state driver to allow
easy identification during failures
* src/libvirt.c: Log name of failed driver for virStateInit
failures
* src/lxc/lxc_driver.c: Don't return a failure code for
lxcStartup() if LXC is not available on this host, simply
disable the driver.
* src/network/bridge_driver.c, src/node_device/node_device_devkit.c,
src/node_device/node_device_hal.c, src/opennebula/one_driver.c,
src/qemu/qemu_driver.c, src/remote/remote_driver.c,
src/secret/secret_driver.c, src/storage/storage_driver.c,
src/uml/uml_driver.c, src/xen/xen_driver.c: Fill in name
field in virStateDriver struct
2009-11-02 23:18:19 +00:00
|
|
|
"Network",
|
2008-10-10 13:57:13 +00:00
|
|
|
networkStartup,
|
|
|
|
networkShutdown,
|
|
|
|
networkReload,
|
|
|
|
networkActive,
|
|
|
|
};
|
|
|
|
|
|
|
|
int networkRegister(void) {
|
|
|
|
virRegisterNetworkDriver(&networkDriver);
|
|
|
|
virRegisterStateDriver(&networkStateDriver);
|
|
|
|
return 0;
|
|
|
|
}
|