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"
|
|
|
|
#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"
|
2008-10-10 13:57:13 +00:00
|
|
|
|
2009-01-20 22:36:10 +00:00
|
|
|
#define NETWORK_PID_DIR LOCAL_STATE_DIR "/run/libvirt/network"
|
|
|
|
#define NETWORK_STATE_DIR LOCAL_STATE_DIR "/lib/libvirt/network"
|
2009-01-20 17:13:33 +00:00
|
|
|
|
2010-04-28 13:38:47 +00:00
|
|
|
#define DNSMASQ_STATE_DIR LOCAL_STATE_DIR "/lib/libvirt/dnsmasq"
|
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;
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
2009-07-30 13:52:31 +00:00
|
|
|
/* Finally try and read dnsmasq pid if any */
|
|
|
|
if ((obj->def->ipAddress ||
|
|
|
|
obj->def->nranges) &&
|
2009-01-20 22:36:10 +00:00
|
|
|
virFileReadPid(NETWORK_PID_DIR, obj->def->name,
|
|
|
|
&obj->dnsmasqPid) == 0) {
|
|
|
|
|
|
|
|
/* Check its still alive */
|
|
|
|
if (kill(obj->dnsmasqPid, 0) != 0)
|
|
|
|
obj->dnsmasqPid = -1;
|
|
|
|
|
|
|
|
#ifdef __linux__
|
|
|
|
char *pidpath;
|
|
|
|
|
2009-10-16 10:09:13 +00:00
|
|
|
if (virAsprintf(&pidpath, "/proc/%d/exe", obj->dnsmasqPid) < 0) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2009-10-16 10:09:13 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2009-01-20 22:36:10 +00:00
|
|
|
if (virFileLinkPointsTo(pidpath, DNSMASQ) == 0)
|
|
|
|
obj->dnsmasqPid = -1;
|
|
|
|
VIR_FREE(pidpath);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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,
|
|
|
|
"%s/log/libvirt/qemu", LOCAL_STATE_DIR) == -1)
|
2008-10-10 13:57:13 +00:00
|
|
|
goto out_of_memory;
|
|
|
|
|
|
|
|
if ((base = strdup (SYSCONF_DIR "/libvirt")) == NULL)
|
|
|
|
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
|
|
|
|
networkSaveDnsmasqHostsfile(virNetworkObjPtr network,
|
|
|
|
dnsmasqContext *dctx,
|
|
|
|
bool force)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
if (! force && virFileExists(dctx->hostsfile->path))
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
for (i = 0 ; i < network->def->nhosts ; i++) {
|
|
|
|
virNetworkDHCPHostDefPtr host = &(network->def->hosts[i]);
|
|
|
|
if ((host->mac) && (host->ip))
|
|
|
|
dnsmasqAddDhcpHost(dctx, host->mac, host->ip, host->name);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dnsmasqSave(dctx) < 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-10 13:57:13 +00:00
|
|
|
static int
|
2010-02-04 18:19:08 +00:00
|
|
|
networkBuildDnsmasqArgv(virNetworkObjPtr network,
|
2009-01-20 22:36:10 +00:00
|
|
|
const char *pidfile,
|
|
|
|
const char ***argv) {
|
2008-10-10 13:57:13 +00:00
|
|
|
int i, len, r;
|
2009-11-06 16:53:45 +00:00
|
|
|
int nbleases = 0;
|
2009-01-20 22:36:10 +00:00
|
|
|
char *pidfileArg;
|
|
|
|
char buf[1024];
|
|
|
|
|
|
|
|
/*
|
|
|
|
* NB, be careful about syntax for dnsmasq options in long format
|
|
|
|
*
|
|
|
|
* 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,
|
|
|
|
* without reading the dnsmasq source :-( The manpages is not
|
|
|
|
* very explicit on this
|
|
|
|
*/
|
2008-10-10 13:57:13 +00:00
|
|
|
|
|
|
|
len =
|
|
|
|
1 + /* dnsmasq */
|
|
|
|
1 + /* --strict-order */
|
|
|
|
1 + /* --bind-interfaces */
|
|
|
|
(network->def->domain?2:0) + /* --domain name */
|
2009-01-20 22:36:10 +00:00
|
|
|
2 + /* --pid-file /var/run/libvirt/network/$NAME.pid */
|
2008-10-10 13:57:13 +00:00
|
|
|
2 + /* --conf-file "" */
|
|
|
|
/*2 + *//* --interface virbr0 */
|
|
|
|
2 + /* --except-interface lo */
|
|
|
|
2 + /* --listen-address 10.0.0.1 */
|
|
|
|
(2 * network->def->nranges) + /* --dhcp-range 10.0.0.2,10.0.0.254 */
|
2009-11-06 16:53:45 +00:00
|
|
|
/* --dhcp-lease-max=xxx if needed */
|
2010-08-11 15:47:18 +00:00
|
|
|
(network->def->nranges ? 1 : 0) +
|
2010-08-11 18:25:09 +00:00
|
|
|
/* --dhcp-no-override if needed */
|
|
|
|
(network->def->nranges ? 1 : 0) +
|
2010-04-26 14:07:25 +00:00
|
|
|
/* --dhcp-hostsfile=/var/lib/dnsmasq/$NAME.hostsfile */
|
|
|
|
(network->def->nhosts > 0 ? 1 : 0) +
|
2009-09-21 20:50:25 +00:00
|
|
|
/* --enable-tftp --tftp-root /srv/tftp */
|
|
|
|
(network->def->tftproot ? 3 : 0) +
|
2009-10-28 14:57:49 +00:00
|
|
|
/* --dhcp-boot pxeboot.img[,,12.34.56.78] */
|
2009-09-21 20:50:25 +00:00
|
|
|
(network->def->bootfile ? 2 : 0) +
|
2008-10-10 13:57:13 +00:00
|
|
|
1; /* NULL */
|
|
|
|
|
|
|
|
if (VIR_ALLOC_N(*argv, len) < 0)
|
|
|
|
goto no_memory;
|
|
|
|
|
|
|
|
#define APPEND_ARG(v, n, s) do { \
|
|
|
|
if (!((v)[(n)] = strdup(s))) \
|
|
|
|
goto no_memory; \
|
|
|
|
} while (0)
|
|
|
|
|
2009-01-20 22:36:10 +00:00
|
|
|
#define APPEND_ARG_LIT(v, n, s) \
|
|
|
|
(v)[(n)] = s
|
|
|
|
|
2008-10-10 13:57:13 +00:00
|
|
|
i = 0;
|
|
|
|
|
|
|
|
APPEND_ARG(*argv, i++, DNSMASQ);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Needed to ensure dnsmasq uses same algorithm for processing
|
|
|
|
* multiple namedriver entries in /etc/resolv.conf as GLibC.
|
|
|
|
*/
|
|
|
|
APPEND_ARG(*argv, i++, "--strict-order");
|
|
|
|
APPEND_ARG(*argv, i++, "--bind-interfaces");
|
|
|
|
|
|
|
|
if (network->def->domain) {
|
|
|
|
APPEND_ARG(*argv, i++, "--domain");
|
|
|
|
APPEND_ARG(*argv, i++, network->def->domain);
|
|
|
|
}
|
|
|
|
|
2009-01-20 22:36:10 +00:00
|
|
|
if (virAsprintf(&pidfileArg, "--pid-file=%s", pidfile) < 0)
|
|
|
|
goto no_memory;
|
|
|
|
APPEND_ARG_LIT(*argv, i++, pidfileArg);
|
2008-10-10 13:57:13 +00:00
|
|
|
|
2009-01-20 22:36:10 +00:00
|
|
|
APPEND_ARG(*argv, i++, "--conf-file=");
|
2008-10-10 13:57:13 +00:00
|
|
|
APPEND_ARG(*argv, i++, "");
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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
|
|
|
|
*
|
|
|
|
* APPEND_ARG(*argv, i++, "--interface");
|
|
|
|
* APPEND_ARG(*argv, i++, network->def->bridge);
|
|
|
|
*/
|
|
|
|
APPEND_ARG(*argv, i++, "--listen-address");
|
|
|
|
APPEND_ARG(*argv, i++, network->def->ipAddress);
|
|
|
|
|
|
|
|
APPEND_ARG(*argv, i++, "--except-interface");
|
|
|
|
APPEND_ARG(*argv, i++, "lo");
|
|
|
|
|
|
|
|
for (r = 0 ; r < network->def->nranges ; r++) {
|
|
|
|
snprintf(buf, sizeof(buf), "%s,%s",
|
|
|
|
network->def->ranges[r].start,
|
|
|
|
network->def->ranges[r].end);
|
|
|
|
|
|
|
|
APPEND_ARG(*argv, i++, "--dhcp-range");
|
|
|
|
APPEND_ARG(*argv, i++, buf);
|
2009-11-06 16:53:45 +00:00
|
|
|
nbleases += network->def->ranges[r].size;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (network->def->nranges > 0) {
|
|
|
|
snprintf(buf, sizeof(buf), "--dhcp-lease-max=%d", nbleases);
|
|
|
|
APPEND_ARG(*argv, i++, buf);
|
2010-08-11 18:25:09 +00:00
|
|
|
APPEND_ARG(*argv, i++, "--dhcp-no-override");
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
|
|
|
|
2010-04-26 14:07:25 +00:00
|
|
|
if (network->def->nhosts > 0) {
|
|
|
|
dnsmasqContext *dctx = dnsmasqContextNew(network->def->name, DNSMASQ_STATE_DIR);
|
|
|
|
char *hostsfileArg;
|
2008-10-10 13:57:13 +00:00
|
|
|
|
2010-04-26 14:07:25 +00:00
|
|
|
if (dctx == NULL)
|
|
|
|
goto no_memory;
|
|
|
|
|
|
|
|
if (networkSaveDnsmasqHostsfile(network, dctx, false)) {
|
|
|
|
if (virAsprintf(&hostsfileArg, "--dhcp-hostsfile=%s", dctx->hostsfile->path) < 0) {
|
|
|
|
dnsmasqContextFree(dctx);
|
|
|
|
goto no_memory;
|
|
|
|
}
|
|
|
|
APPEND_ARG_LIT(*argv, i++, hostsfileArg);
|
|
|
|
}
|
|
|
|
|
|
|
|
dnsmasqContextFree(dctx);
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
|
|
|
|
2009-09-21 20:50:25 +00:00
|
|
|
if (network->def->tftproot) {
|
|
|
|
APPEND_ARG(*argv, i++, "--enable-tftp");
|
|
|
|
APPEND_ARG(*argv, i++, "--tftp-root");
|
|
|
|
APPEND_ARG(*argv, i++, network->def->tftproot);
|
|
|
|
}
|
|
|
|
if (network->def->bootfile) {
|
2009-10-28 14:57:49 +00:00
|
|
|
snprintf(buf, sizeof(buf), "%s%s%s",
|
|
|
|
network->def->bootfile,
|
|
|
|
network->def->bootserver ? ",," : "",
|
|
|
|
network->def->bootserver ? network->def->bootserver : "");
|
|
|
|
|
2009-09-21 20:50:25 +00:00
|
|
|
APPEND_ARG(*argv, i++, "--dhcp-boot");
|
2009-10-28 14:57:49 +00:00
|
|
|
APPEND_ARG(*argv, i++, buf);
|
2009-09-21 20:50:25 +00:00
|
|
|
}
|
|
|
|
|
2008-10-10 13:57:13 +00:00
|
|
|
#undef APPEND_ARG
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
no_memory:
|
2010-01-05 14:48:42 +00:00
|
|
|
if (*argv) {
|
2008-10-10 13:57:13 +00:00
|
|
|
for (i = 0; (*argv)[i]; i++)
|
|
|
|
VIR_FREE((*argv)[i]);
|
|
|
|
VIR_FREE(*argv);
|
|
|
|
}
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2008-10-10 13:57:13 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2010-02-10 10:22:52 +00:00
|
|
|
dhcpStartDhcpDaemon(virNetworkObjPtr network)
|
2008-10-10 13:57:13 +00:00
|
|
|
{
|
|
|
|
const char **argv;
|
2009-01-20 22:36:10 +00:00
|
|
|
char *pidfile;
|
|
|
|
int ret = -1, i, err;
|
|
|
|
|
|
|
|
network->dnsmasqPid = -1;
|
2008-10-10 13:57:13 +00:00
|
|
|
|
|
|
|
if (network->def->ipAddress == NULL) {
|
2010-02-10 10:22:52 +00:00
|
|
|
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("cannot start dhcp daemon without IP address for server"));
|
2008-10-10 13:57:13 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
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);
|
|
|
|
return -1;
|
|
|
|
}
|
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);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(pidfile = virFilePid(NETWORK_PID_DIR, network->def->name))) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2009-01-20 22:36:10 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2008-10-10 13:57:13 +00:00
|
|
|
argv = NULL;
|
2010-02-04 18:19:08 +00:00
|
|
|
if (networkBuildDnsmasqArgv(network, pidfile, &argv) < 0) {
|
2009-01-20 22:36:10 +00:00
|
|
|
VIR_FREE(pidfile);
|
2008-10-10 13:57:13 +00:00
|
|
|
return -1;
|
2009-01-20 22:36:10 +00:00
|
|
|
}
|
|
|
|
|
2010-02-04 22:41:52 +00:00
|
|
|
if (virRun(argv, NULL) < 0)
|
2009-01-20 22:36:10 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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 virRun exits
|
|
|
|
* it has waitpid'd and guaranteed the proess has started
|
|
|
|
* and written a pid
|
|
|
|
*/
|
|
|
|
|
|
|
|
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;
|
2008-10-10 13:57:13 +00:00
|
|
|
|
2009-01-20 22:36:10 +00:00
|
|
|
cleanup:
|
|
|
|
VIR_FREE(pidfile);
|
2008-10-10 13:57:13 +00:00
|
|
|
for (i = 0; argv[i]; i++)
|
|
|
|
VIR_FREE(argv[i]);
|
|
|
|
VIR_FREE(argv);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2010-02-04 20:02:58 +00:00
|
|
|
networkAddMasqueradingIptablesRules(struct network_driver *driver,
|
|
|
|
virNetworkObjPtr network) {
|
2008-10-10 13:57:13 +00:00
|
|
|
int err;
|
|
|
|
/* allow forwarding packets from the bridge interface */
|
|
|
|
if ((err = iptablesAddForwardAllowOut(driver->iptables,
|
|
|
|
network->def->network,
|
|
|
|
network->def->bridge,
|
|
|
|
network->def->forwardDev))) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(err,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("failed to add iptables rule to allow forwarding from '%s'"),
|
|
|
|
network->def->bridge);
|
2008-10-10 13:57:13 +00:00
|
|
|
goto masqerr1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* allow forwarding packets to the bridge interface if they are part of an existing connection */
|
|
|
|
if ((err = iptablesAddForwardAllowRelatedIn(driver->iptables,
|
|
|
|
network->def->network,
|
|
|
|
network->def->bridge,
|
|
|
|
network->def->forwardDev))) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(err,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("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 */
|
2008-10-10 13:57:13 +00:00
|
|
|
if ((err = iptablesAddForwardMasquerade(driver->iptables,
|
|
|
|
network->def->network,
|
2010-06-10 16:50:38 +00:00
|
|
|
network->def->forwardDev,
|
|
|
|
NULL))) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(err,
|
2010-05-20 09:12:17 +00:00
|
|
|
_("failed to add iptables rule to enable masquerading to '%s'"),
|
2009-01-20 17:13:33 +00:00
|
|
|
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 */
|
|
|
|
if ((err = iptablesAddForwardMasquerade(driver->iptables,
|
|
|
|
network->def->network,
|
|
|
|
network->def->forwardDev,
|
|
|
|
"udp"))) {
|
|
|
|
virReportSystemError(err,
|
|
|
|
_("failed to add iptables rule to enable UDP masquerading to '%s'"),
|
|
|
|
network->def->forwardDev ? network->def->forwardDev : NULL);
|
|
|
|
goto masqerr4;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* TCP with a source port restriction */
|
|
|
|
if ((err = iptablesAddForwardMasquerade(driver->iptables,
|
|
|
|
network->def->network,
|
|
|
|
network->def->forwardDev,
|
|
|
|
"tcp"))) {
|
|
|
|
virReportSystemError(err,
|
|
|
|
_("failed to add iptables rule to enable TCP masquerading to '%s'"),
|
|
|
|
network->def->forwardDev ? network->def->forwardDev : NULL);
|
|
|
|
goto masqerr5;
|
|
|
|
}
|
|
|
|
|
2008-10-10 13:57:13 +00:00
|
|
|
return 1;
|
|
|
|
|
2010-06-10 16:50:38 +00:00
|
|
|
masqerr5:
|
|
|
|
iptablesRemoveForwardMasquerade(driver->iptables,
|
|
|
|
network->def->network,
|
|
|
|
network->def->forwardDev,
|
|
|
|
"udp");
|
|
|
|
masqerr4:
|
|
|
|
iptablesRemoveForwardMasquerade(driver->iptables,
|
|
|
|
network->def->network,
|
|
|
|
network->def->forwardDev,
|
|
|
|
NULL);
|
2008-10-10 13:57:13 +00:00
|
|
|
masqerr3:
|
|
|
|
iptablesRemoveForwardAllowRelatedIn(driver->iptables,
|
|
|
|
network->def->network,
|
|
|
|
network->def->bridge,
|
|
|
|
network->def->forwardDev);
|
|
|
|
masqerr2:
|
|
|
|
iptablesRemoveForwardAllowOut(driver->iptables,
|
|
|
|
network->def->network,
|
|
|
|
network->def->bridge,
|
|
|
|
network->def->forwardDev);
|
|
|
|
masqerr1:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2010-02-04 20:02:58 +00:00
|
|
|
networkAddRoutingIptablesRules(struct network_driver *driver,
|
|
|
|
virNetworkObjPtr network) {
|
2008-10-10 13:57:13 +00:00
|
|
|
int err;
|
|
|
|
/* allow routing packets from the bridge interface */
|
|
|
|
if ((err = iptablesAddForwardAllowOut(driver->iptables,
|
|
|
|
network->def->network,
|
|
|
|
network->def->bridge,
|
|
|
|
network->def->forwardDev))) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(err,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("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 */
|
|
|
|
if ((err = iptablesAddForwardAllowIn(driver->iptables,
|
|
|
|
network->def->network,
|
|
|
|
network->def->bridge,
|
|
|
|
network->def->forwardDev))) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(err,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("failed to add iptables rule to allow routing to '%s'"),
|
|
|
|
network->def->bridge);
|
2008-10-10 13:57:13 +00:00
|
|
|
goto routeerr2;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
|
|
|
|
routeerr2:
|
|
|
|
iptablesRemoveForwardAllowOut(driver->iptables,
|
|
|
|
network->def->network,
|
|
|
|
network->def->bridge,
|
|
|
|
network->def->forwardDev);
|
|
|
|
routeerr1:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2010-02-04 20:02:58 +00:00
|
|
|
networkAddIptablesRules(struct network_driver *driver,
|
|
|
|
virNetworkObjPtr network) {
|
2008-10-10 13:57:13 +00:00
|
|
|
int err;
|
|
|
|
|
|
|
|
/* allow DHCP requests through to dnsmasq */
|
|
|
|
if ((err = iptablesAddTcpInput(driver->iptables, network->def->bridge, 67))) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(err,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("failed to add iptables rule to allow DHCP requests from '%s'"),
|
|
|
|
network->def->bridge);
|
2008-10-10 13:57:13 +00:00
|
|
|
goto err1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((err = iptablesAddUdpInput(driver->iptables, network->def->bridge, 67))) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(err,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("failed to add iptables rule to allow DHCP requests from '%s'"),
|
|
|
|
network->def->bridge);
|
2008-10-10 13:57:13 +00:00
|
|
|
goto err2;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* allow DNS requests through to dnsmasq */
|
|
|
|
if ((err = iptablesAddTcpInput(driver->iptables, network->def->bridge, 53))) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(err,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("failed to add iptables rule to allow DNS requests from '%s'"),
|
|
|
|
network->def->bridge);
|
2008-10-10 13:57:13 +00:00
|
|
|
goto err3;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((err = iptablesAddUdpInput(driver->iptables, network->def->bridge, 53))) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(err,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("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-06-19 18:08:26 +00:00
|
|
|
/* allow TFTP requests through to dnsmasq */
|
|
|
|
if (network->def->tftproot &&
|
|
|
|
(err = iptablesAddUdpInput(driver->iptables, network->def->bridge, 69))) {
|
|
|
|
virReportSystemError(err,
|
|
|
|
_("failed to add iptables rule to allow TFTP requests from '%s'"),
|
|
|
|
network->def->bridge);
|
|
|
|
goto err4tftp;
|
|
|
|
}
|
|
|
|
|
2008-10-10 13:57:13 +00:00
|
|
|
|
|
|
|
/* Catch all rules to block forwarding to/from bridges */
|
|
|
|
|
|
|
|
if ((err = iptablesAddForwardRejectOut(driver->iptables, network->def->bridge))) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(err,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("failed to add iptables rule to block outbound traffic from '%s'"),
|
|
|
|
network->def->bridge);
|
2008-10-10 13:57:13 +00:00
|
|
|
goto err5;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((err = iptablesAddForwardRejectIn(driver->iptables, network->def->bridge))) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(err,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("failed to add iptables rule to block inbound traffic to '%s'"),
|
|
|
|
network->def->bridge);
|
2008-10-10 13:57:13 +00:00
|
|
|
goto err6;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Allow traffic between guests on the same bridge */
|
|
|
|
if ((err = iptablesAddForwardAllowCross(driver->iptables, network->def->bridge))) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(err,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("failed to add iptables rule to allow cross bridge traffic on '%s'"),
|
|
|
|
network->def->bridge);
|
2008-10-10 13:57:13 +00:00
|
|
|
goto err7;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* If masquerading is enabled, set up the rules*/
|
|
|
|
if (network->def->forwardType == VIR_NETWORK_FORWARD_NAT &&
|
2010-02-04 20:02:58 +00:00
|
|
|
!networkAddMasqueradingIptablesRules(driver, network))
|
2008-10-10 13:57:13 +00:00
|
|
|
goto err8;
|
|
|
|
/* else if routing is enabled, set up the rules*/
|
|
|
|
else if (network->def->forwardType == VIR_NETWORK_FORWARD_ROUTE &&
|
2010-02-04 20:02:58 +00:00
|
|
|
!networkAddRoutingIptablesRules(driver, network))
|
2008-10-10 13:57:13 +00:00
|
|
|
goto err8;
|
|
|
|
|
2010-07-13 02:59:58 +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 ((network->def->ipAddress || network->def->nranges) &&
|
|
|
|
(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
|
|
|
return 1;
|
|
|
|
|
|
|
|
err8:
|
|
|
|
iptablesRemoveForwardAllowCross(driver->iptables,
|
|
|
|
network->def->bridge);
|
|
|
|
err7:
|
|
|
|
iptablesRemoveForwardRejectIn(driver->iptables,
|
|
|
|
network->def->bridge);
|
|
|
|
err6:
|
|
|
|
iptablesRemoveForwardRejectOut(driver->iptables,
|
|
|
|
network->def->bridge);
|
|
|
|
err5:
|
2010-06-19 18:08:26 +00:00
|
|
|
if (network->def->tftproot) {
|
|
|
|
iptablesRemoveUdpInput(driver->iptables, network->def->bridge, 69);
|
|
|
|
}
|
|
|
|
err4tftp:
|
2008-10-10 13:57:13 +00:00
|
|
|
iptablesRemoveUdpInput(driver->iptables, network->def->bridge, 53);
|
|
|
|
err4:
|
|
|
|
iptablesRemoveTcpInput(driver->iptables, network->def->bridge, 53);
|
|
|
|
err3:
|
|
|
|
iptablesRemoveUdpInput(driver->iptables, network->def->bridge, 67);
|
|
|
|
err2:
|
|
|
|
iptablesRemoveTcpInput(driver->iptables, network->def->bridge, 67);
|
|
|
|
err1:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
networkRemoveIptablesRules(struct network_driver *driver,
|
|
|
|
virNetworkObjPtr network) {
|
2010-07-13 02:59:58 +00:00
|
|
|
if (network->def->ipAddress || network->def->nranges) {
|
|
|
|
iptablesRemoveOutputFixUdpChecksum(driver->iptables,
|
|
|
|
network->def->bridge, 68);
|
|
|
|
}
|
2008-10-10 13:57:13 +00:00
|
|
|
if (network->def->forwardType != VIR_NETWORK_FORWARD_NONE) {
|
2009-11-05 19:28:11 +00:00
|
|
|
if (network->def->forwardType == VIR_NETWORK_FORWARD_NAT) {
|
|
|
|
iptablesRemoveForwardMasquerade(driver->iptables,
|
2010-06-10 16:50:38 +00:00
|
|
|
network->def->network,
|
|
|
|
network->def->forwardDev,
|
|
|
|
"tcp");
|
|
|
|
iptablesRemoveForwardMasquerade(driver->iptables,
|
|
|
|
network->def->network,
|
|
|
|
network->def->forwardDev,
|
|
|
|
"udp");
|
|
|
|
iptablesRemoveForwardMasquerade(driver->iptables,
|
|
|
|
network->def->network,
|
|
|
|
network->def->forwardDev,
|
|
|
|
NULL);
|
2008-10-10 13:57:13 +00:00
|
|
|
iptablesRemoveForwardAllowRelatedIn(driver->iptables,
|
|
|
|
network->def->network,
|
|
|
|
network->def->bridge,
|
|
|
|
network->def->forwardDev);
|
2009-11-05 19:28:11 +00:00
|
|
|
} else if (network->def->forwardType == VIR_NETWORK_FORWARD_ROUTE)
|
2008-10-10 13:57:13 +00:00
|
|
|
iptablesRemoveForwardAllowIn(driver->iptables,
|
|
|
|
network->def->network,
|
|
|
|
network->def->bridge,
|
|
|
|
network->def->forwardDev);
|
|
|
|
|
|
|
|
iptablesRemoveForwardAllowOut(driver->iptables,
|
|
|
|
network->def->network,
|
|
|
|
network->def->bridge,
|
|
|
|
network->def->forwardDev);
|
|
|
|
}
|
|
|
|
iptablesRemoveForwardAllowCross(driver->iptables, network->def->bridge);
|
|
|
|
iptablesRemoveForwardRejectIn(driver->iptables, network->def->bridge);
|
|
|
|
iptablesRemoveForwardRejectOut(driver->iptables, network->def->bridge);
|
2010-06-19 18:08:26 +00:00
|
|
|
iptablesRemoveUdpInput(driver->iptables, network->def->bridge, 69);
|
2008-10-10 13:57:13 +00:00
|
|
|
iptablesRemoveUdpInput(driver->iptables, network->def->bridge, 53);
|
|
|
|
iptablesRemoveTcpInput(driver->iptables, network->def->bridge, 53);
|
|
|
|
iptablesRemoveUdpInput(driver->iptables, network->def->bridge, 67);
|
|
|
|
iptablesRemoveTcpInput(driver->iptables, network->def->bridge, 67);
|
|
|
|
}
|
|
|
|
|
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])) {
|
|
|
|
networkRemoveIptablesRules(driver, driver->networks.objs[i]);
|
2010-02-04 20:02:58 +00:00
|
|
|
if (!networkAddIptablesRules(driver, driver->networks.objs[i])) {
|
2009-12-10 11:27:17 +00:00
|
|
|
/* failed to add but already logged */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
networkEnableIpForwarding(void)
|
|
|
|
{
|
2009-02-13 19:13:06 +00:00
|
|
|
return virFileWriteStr("/proc/sys/net/ipv4/ip_forward", "1\n");
|
2008-10-10 13:57:13 +00:00
|
|
|
}
|
|
|
|
|
2009-07-30 15:34:56 +00:00
|
|
|
#define SYSCTL_PATH "/proc/sys"
|
|
|
|
|
2010-02-04 20:02:58 +00:00
|
|
|
static int networkDisableIPV6(virNetworkObjPtr network)
|
2009-07-30 15:34:56 +00:00
|
|
|
{
|
|
|
|
char *field = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (virAsprintf(&field, SYSCTL_PATH "/net/ipv6/conf/%s/disable_ipv6", network->def->bridge) < 0) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2009-07-30 15:34:56 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2009-08-10 10:16:37 +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-07-30 15:34:56 +00:00
|
|
|
if (virFileWriteStr(field, "1") < 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;
|
|
|
|
}
|
|
|
|
VIR_FREE(field);
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virFileWriteStr(field, "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);
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virFileWriteStr(field, "1") < 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
|
|
|
|
*/
|
|
|
|
static int networkCheckRouteCollision(virNetworkObjPtr network)
|
|
|
|
{
|
|
|
|
int ret = -1, len;
|
|
|
|
unsigned int net_dest;
|
|
|
|
char *cur, *buf = NULL;
|
|
|
|
enum {MAX_ROUTE_SIZE = 1024*64};
|
|
|
|
virSocketAddr inaddress, innetmask;
|
|
|
|
|
|
|
|
if (!network->def->ipAddress || !network->def->netmask)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (virSocketParseAddr(network->def->ipAddress, &inaddress, 0) < 0) {
|
|
|
|
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("cannot parse IP address '%s'"),
|
|
|
|
network->def->ipAddress);
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virSocketParseAddr(network->def->netmask, &innetmask, 0) < 0) {
|
|
|
|
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("cannot parse netmask '%s'"),
|
|
|
|
network->def->netmask);
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (inaddress.stor.ss_family != AF_INET ||
|
|
|
|
innetmask.stor.ss_family != AF_INET) {
|
|
|
|
/* Only support collision check for IPv4 */
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
net_dest = (inaddress.inet4.sin_addr.s_addr &
|
|
|
|
innetmask.inet4.sin_addr.s_addr);
|
|
|
|
|
|
|
|
/* Read whole routing table into memory */
|
|
|
|
if ((len = virFileReadAll(PROC_NET_ROUTE, MAX_ROUTE_SIZE, &buf)) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
/* 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;
|
|
|
|
int num;
|
|
|
|
|
|
|
|
/* 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;
|
|
|
|
|
|
|
|
if ((net_dest == addr_val) &&
|
|
|
|
(innetmask.inet4.sin_addr.s_addr == mask_val)) {
|
|
|
|
networkReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Network %s/%s is already in use by "
|
|
|
|
"interface %s"),
|
|
|
|
network->def->ipAddress,
|
|
|
|
network->def->netmask, iface);
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
out:
|
|
|
|
ret = 0;
|
|
|
|
error:
|
|
|
|
VIR_FREE(buf);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
int err;
|
|
|
|
|
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-05-20 23:31:16 +00:00
|
|
|
/* Check to see if network collides with an existing route */
|
|
|
|
if (networkCheckRouteCollision(network) < 0)
|
|
|
|
return -1;
|
|
|
|
|
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-02-04 20:02:58 +00:00
|
|
|
if (networkDisableIPV6(network) < 0)
|
2009-07-30 15:34:56 +00:00
|
|
|
goto err_delbr;
|
|
|
|
|
2008-10-10 13:57:13 +00:00
|
|
|
if (brSetForwardDelay(driver->brctl, network->def->bridge, network->def->delay) < 0)
|
|
|
|
goto err_delbr;
|
|
|
|
|
|
|
|
if (brSetEnableSTP(driver->brctl, network->def->bridge, network->def->stp ? 1 : 0) < 0)
|
|
|
|
goto err_delbr;
|
|
|
|
|
|
|
|
if (network->def->ipAddress &&
|
|
|
|
(err = brSetInetAddress(driver->brctl, network->def->bridge, network->def->ipAddress))) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(err,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("cannot set IP address on bridge '%s' to '%s'"),
|
|
|
|
network->def->bridge, network->def->ipAddress);
|
2008-10-10 13:57:13 +00:00
|
|
|
goto err_delbr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (network->def->netmask &&
|
|
|
|
(err = brSetInetNetmask(driver->brctl, network->def->bridge, network->def->netmask))) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(err,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("cannot set netmask on bridge '%s' to '%s'"),
|
|
|
|
network->def->bridge, network->def->netmask);
|
2008-10-10 13:57:13 +00:00
|
|
|
goto err_delbr;
|
|
|
|
}
|
|
|
|
|
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);
|
2008-10-10 13:57:13 +00:00
|
|
|
goto err_delbr;
|
|
|
|
}
|
|
|
|
|
2010-02-04 20:02:58 +00:00
|
|
|
if (!networkAddIptablesRules(driver, network))
|
2008-10-10 13:57:13 +00:00
|
|
|
goto err_delbr1;
|
|
|
|
|
|
|
|
if (network->def->forwardType != VIR_NETWORK_FORWARD_NONE &&
|
2009-02-22 11:19:54 +00:00
|
|
|
networkEnableIpForwarding() < 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"));
|
2008-10-10 13:57:13 +00:00
|
|
|
goto err_delbr2;
|
|
|
|
}
|
|
|
|
|
2009-07-30 13:52:31 +00:00
|
|
|
if ((network->def->ipAddress ||
|
|
|
|
network->def->nranges) &&
|
2010-02-10 10:22:52 +00:00
|
|
|
dhcpStartDhcpDaemon(network) < 0)
|
2008-10-10 13:57:13 +00:00
|
|
|
goto err_delbr2;
|
|
|
|
|
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) {
|
2009-01-20 22:36:10 +00:00
|
|
|
goto err_kill;
|
|
|
|
}
|
|
|
|
|
2008-10-10 13:57:13 +00:00
|
|
|
network->active = 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
2009-01-20 22:36:10 +00:00
|
|
|
err_kill:
|
|
|
|
if (network->dnsmasqPid > 0) {
|
|
|
|
kill(network->dnsmasqPid, SIGTERM);
|
|
|
|
network->dnsmasqPid = -1;
|
|
|
|
}
|
|
|
|
|
2008-10-10 13:57:13 +00:00
|
|
|
err_delbr2:
|
|
|
|
networkRemoveIptablesRules(driver, network);
|
|
|
|
|
|
|
|
err_delbr1:
|
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
|
|
|
}
|
|
|
|
|
|
|
|
err_delbr:
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
2008-10-10 13:57:13 +00:00
|
|
|
if (network->dnsmasqPid > 0)
|
|
|
|
kill(network->dnsmasqPid, SIGTERM);
|
|
|
|
|
|
|
|
networkRemoveIptablesRules(driver, network);
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
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;
|
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-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-04-26 14:07:25 +00:00
|
|
|
if (network->def->nhosts > 0) {
|
|
|
|
dnsmasqContext *dctx = dnsmasqContextNew(network->def->name, DNSMASQ_STATE_DIR);
|
|
|
|
if (dctx == NULL)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
networkSaveDnsmasqHostsfile(network, dctx, true);
|
|
|
|
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;
|
2008-12-04 21:38:38 +00:00
|
|
|
virNetworkObjPtr network = 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-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-04-26 14:07:25 +00:00
|
|
|
if (network->def->nhosts > 0) {
|
|
|
|
dnsmasqContext *dctx = dnsmasqContextNew(network->def->name, DNSMASQ_STATE_DIR);
|
|
|
|
if (dctx == NULL)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
dnsmasqDelete(dctx);
|
|
|
|
dnsmasqContextFree(dctx);
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
}
|