]> xenbits.xensource.com Git - people/liuw/libxenctrl-split/libvirt.git/commitdiff
Move network driver into src/network
authorDaniel P. Berrange <berrange@redhat.com>
Tue, 15 Sep 2009 17:52:58 +0000 (18:52 +0100)
committerDaniel P. Berrange <berrange@redhat.com>
Mon, 21 Sep 2009 13:41:44 +0000 (14:41 +0100)
* daemon/qemud.c, src/Makefile.am: Adapt for changed paths
* src/network_driver.c: Rename to src/network/bridge_driver.c
* src/network_driver.h: Rename to src/network/bridge_driver.h

daemon/qemud.c
src/Makefile.am
src/network/bridge_driver.c [new file with mode: 0644]
src/network/bridge_driver.h [new file with mode: 0644]
src/network_driver.c [deleted file]
src/network_driver.h [deleted file]

index 67c49b389d40a187a87069bfa6653fde811b51a9..9a6f0fff94b055f1a7faebe7b97def08d83d7f4d 100644 (file)
@@ -81,7 +81,7 @@
 #include "opennebula/one_driver.h"
 #endif
 #ifdef WITH_NETWORK
-#include "network_driver.h"
+#include "network/bridge_driver.h"
 #endif
 #ifdef WITH_NETCF
 #include "interface_driver.h"
index 0586338cba1c5eaf7f0b9aa564957273ffea3d47..97a8c3863ab58e94430419cf51730f3fcfafe2bb 100644 (file)
@@ -177,7 +177,7 @@ ESX_DRIVER_SOURCES =                                                \
                esx/esx_vmx.c esx/esx_vmx.h
 
 NETWORK_DRIVER_SOURCES =                                       \
-               network_driver.h network_driver.c
+               network/bridge_driver.h network/bridge_driver.c
 
 INTERFACE_DRIVER_SOURCES =                                     \
                interface_driver.h interface_driver.c
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
new file mode 100644 (file)
index 0000000..fd3d08f
--- /dev/null
@@ -0,0 +1,1499 @@
+/*
+ * driver.c: core driver methods for managing qemu guests
+ *
+ * Copyright (C) 2006-2009 Red Hat, Inc.
+ * 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 <strings.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>
+
+#include "virterror_internal.h"
+#include "datatypes.h"
+#include "bridge_driver.h"
+#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"
+#include "logging.h"
+
+#define NETWORK_PID_DIR LOCAL_STATE_DIR "/run/libvirt/network"
+#define NETWORK_STATE_DIR LOCAL_STATE_DIR "/lib/libvirt/network"
+
+#define VIR_FROM_THIS VIR_FROM_NETWORK
+
+/* Main driver state */
+struct network_driver {
+    virMutex lock;
+
+    virNetworkObjList networks;
+
+    iptablesContext *iptables;
+    brControl *brctl;
+    char *networkConfigDir;
+    char *networkAutostartDir;
+    char *logDir;
+};
+
+
+static void networkDriverLock(struct network_driver *driver)
+{
+    virMutexLock(&driver->lock);
+}
+static void networkDriverUnlock(struct network_driver *driver)
+{
+    virMutexUnlock(&driver->lock);
+}
+
+static int networkShutdown(void);
+
+static int networkStartNetworkDaemon(virConnectPtr conn,
+                                   struct network_driver *driver,
+                                   virNetworkObjPtr network);
+
+static int networkShutdownNetworkDaemon(virConnectPtr conn,
+                                      struct network_driver *driver,
+                                      virNetworkObjPtr network);
+
+static struct network_driver *driverState = NULL;
+
+
+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);
+
+        if ((config = virNetworkConfigFile(NULL,
+                                           NETWORK_STATE_DIR,
+                                           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 */
+        tmp = virNetworkDefParseFile(NULL, config);
+        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;
+
+            /* Finally try and read dnsmasq pid if any */
+            if ((obj->def->ipAddress ||
+                 obj->def->nranges) &&
+                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;
+
+                virAsprintf(&pidpath, "/proc/%d/exe", obj->dnsmasqPid);
+                if (virFileLinkPointsTo(pidpath, DNSMASQ) == 0)
+                    obj->dnsmasqPid = -1;
+                VIR_FREE(pidpath);
+#endif
+            }
+        }
+
+        virNetworkObjUnlock(obj);
+    }
+}
+
+
+static void
+networkAutostartConfigs(struct network_driver *driver) {
+    unsigned int i;
+
+    for (i = 0 ; i < driver->networks.count ; i++) {
+        virNetworkObjLock(driver->networks.objs[i]);
+        if (driver->networks.objs[i]->autostart &&
+            !virNetworkIsActive(driver->networks.objs[i]) &&
+            networkStartNetworkDaemon(NULL, driver, driver->networks.objs[i]) < 0) {
+            /* failed to start but already logged */
+        }
+        virNetworkObjUnlock(driver->networks.objs[i]);
+    }
+}
+
+/**
+ * networkStartup:
+ *
+ * Initialization function for the QEmu daemon
+ */
+static int
+networkStartup(int privileged) {
+    uid_t uid = geteuid();
+    char *base = NULL;
+    int err;
+
+    if (VIR_ALLOC(driverState) < 0)
+        goto error;
+
+    if (virMutexInit(&driverState->lock) < 0) {
+        VIR_FREE(driverState);
+        goto error;
+    }
+    networkDriverLock(driverState);
+
+    if (privileged) {
+        if (virAsprintf(&driverState->logDir,
+                        "%s/log/libvirt/qemu", LOCAL_STATE_DIR) == -1)
+            goto out_of_memory;
+
+        if ((base = strdup (SYSCONF_DIR "/libvirt")) == NULL)
+            goto out_of_memory;
+    } else {
+        char *userdir = virGetUserDirectory(NULL, uid);
+
+        if (!userdir)
+            goto error;
+
+        if (virAsprintf(&driverState->logDir,
+                        "%s/.libvirt/qemu/log", userdir) == -1) {
+            VIR_FREE(userdir);
+            goto out_of_memory;
+        }
+
+        if (virAsprintf(&base, "%s/.libvirt", userdir) == -1) {
+            VIR_FREE(userdir);
+            goto out_of_memory;
+        }
+        VIR_FREE(userdir);
+    }
+
+    /* Configuration paths are either ~/.libvirt/qemu/... (session) or
+     * /etc/libvirt/qemu/... (system).
+     */
+    if (virAsprintf(&driverState->networkConfigDir, "%s/qemu/networks", base) == -1)
+        goto out_of_memory;
+
+    if (virAsprintf(&driverState->networkAutostartDir, "%s/qemu/networks/autostart",
+                    base) == -1)
+        goto out_of_memory;
+
+    VIR_FREE(base);
+
+    if ((err = brInit(&driverState->brctl))) {
+        virReportSystemError(NULL, err, "%s",
+                             _("cannot initialize bridge support"));
+        goto error;
+    }
+
+    if (!(driverState->iptables = iptablesContextNew())) {
+        goto out_of_memory;
+    }
+
+
+    if (virNetworkLoadAllConfigs(NULL,
+                                 &driverState->networks,
+                                 driverState->networkConfigDir,
+                                 driverState->networkAutostartDir) < 0)
+        goto error;
+
+    networkFindActiveConfigs(driverState);
+    networkAutostartConfigs(driverState);
+
+    networkDriverUnlock(driverState);
+
+    return 0;
+
+out_of_memory:
+    virReportOOMError(NULL);
+
+error:
+    if (driverState)
+        networkDriverUnlock(driverState);
+
+    VIR_FREE(base);
+    networkShutdown();
+    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) {
+    if (!driverState)
+        return 0;
+
+    networkDriverLock(driverState);
+    virNetworkLoadAllConfigs(NULL,
+                             &driverState->networks,
+                             driverState->networkConfigDir,
+                             driverState->networkAutostartDir);
+
+     if (driverState->iptables) {
+        VIR_INFO0(_("Reloading iptables rules\n"));
+        iptablesReloadRules(driverState->iptables);
+    }
+
+    networkAutostartConfigs(driverState);
+    networkDriverUnlock(driverState);
+    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) {
+    unsigned int i;
+    int active = 0;
+
+    if (!driverState)
+        return 0;
+
+    networkDriverLock(driverState);
+    for (i = 0 ; i < driverState->networks.count ; i++) {
+        virNetworkObjPtr net = driverState->networks.objs[i];
+        virNetworkObjLock(net);
+        if (virNetworkIsActive(net))
+            active = 1;
+        virNetworkObjUnlock(net);
+    }
+    networkDriverUnlock(driverState);
+    return active;
+}
+
+/**
+ * networkShutdown:
+ *
+ * Shutdown the QEmu daemon, it will stop all active domains and networks
+ */
+static int
+networkShutdown(void) {
+    if (!driverState)
+        return -1;
+
+    networkDriverLock(driverState);
+
+    /* free inactive networks */
+    virNetworkObjListFree(&driverState->networks);
+
+    VIR_FREE(driverState->logDir);
+    VIR_FREE(driverState->networkConfigDir);
+    VIR_FREE(driverState->networkAutostartDir);
+
+    if (driverState->brctl)
+        brShutdown(driverState->brctl);
+    if (driverState->iptables)
+        iptablesContextFree(driverState->iptables);
+
+    networkDriverUnlock(driverState);
+    virMutexDestroy(&driverState->lock);
+
+    VIR_FREE(driverState);
+
+    return 0;
+}
+
+
+static int
+networkBuildDnsmasqArgv(virConnectPtr conn,
+                        virNetworkObjPtr network,
+                        const char *pidfile,
+                        const char ***argv) {
+    int i, len, r;
+    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
+     */
+
+    len =
+        1 + /* dnsmasq */
+        1 + /* --strict-order */
+        1 + /* --bind-interfaces */
+        (network->def->domain?2:0) + /* --domain name */
+        2 + /* --pid-file /var/run/libvirt/network/$NAME.pid */
+        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 */
+        /*  --dhcp-host 01:23:45:67:89:0a,hostname,10.0.0.3 */
+        (2 * network->def->nhosts) +
+        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)
+
+#define APPEND_ARG_LIT(v, n, s) \
+        (v)[(n)] = s
+
+    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);
+    }
+
+    if (virAsprintf(&pidfileArg, "--pid-file=%s", pidfile) < 0)
+        goto no_memory;
+    APPEND_ARG_LIT(*argv, i++, pidfileArg);
+
+    APPEND_ARG(*argv, i++, "--conf-file=");
+    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);
+    }
+
+    for (r = 0 ; r < network->def->nhosts ; r++) {
+        virNetworkDHCPHostDefPtr host = &(network->def->hosts[r]);
+        if ((host->mac) && (host->name)) {
+            snprintf(buf, sizeof(buf), "%s,%s,%s",
+                     host->mac, host->name, host->ip);
+        } else if (host->mac) {
+            snprintf(buf, sizeof(buf), "%s,%s",
+                     host->mac, host->ip);
+        } else if (host->name) {
+            snprintf(buf, sizeof(buf), "%s,%s",
+                     host->name, host->ip);
+        } else
+            continue;
+
+        APPEND_ARG(*argv, i++, "--dhcp-host");
+        APPEND_ARG(*argv, i++, buf);
+    }
+
+#undef APPEND_ARG
+
+    return 0;
+
+ no_memory:
+    if (argv) {
+        for (i = 0; (*argv)[i]; i++)
+            VIR_FREE((*argv)[i]);
+        VIR_FREE(*argv);
+    }
+    virReportOOMError(conn);
+    return -1;
+}
+
+
+static int
+dhcpStartDhcpDaemon(virConnectPtr conn,
+                    virNetworkObjPtr network)
+{
+    const char **argv;
+    char *pidfile;
+    int ret = -1, i, err;
+
+    network->dnsmasqPid = -1;
+
+    if (network->def->ipAddress == NULL) {
+        networkReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+                         "%s", _("cannot start dhcp daemon without IP address for server"));
+        return -1;
+    }
+
+    if ((err = virFileMakePath(NETWORK_PID_DIR)) < 0) {
+        virReportSystemError(conn, err,
+                             _("cannot create directory %s"),
+                             NETWORK_PID_DIR);
+        return -1;
+    }
+    if ((err = virFileMakePath(NETWORK_STATE_DIR)) < 0) {
+        virReportSystemError(conn, err,
+                             _("cannot create directory %s"),
+                             NETWORK_STATE_DIR);
+        return -1;
+    }
+
+    if (!(pidfile = virFilePid(NETWORK_PID_DIR, network->def->name))) {
+        virReportOOMError(conn);
+        return -1;
+    }
+
+    argv = NULL;
+    if (networkBuildDnsmasqArgv(conn, network, pidfile, &argv) < 0) {
+        VIR_FREE(pidfile);
+        return -1;
+    }
+
+    if (virRun(conn, argv, NULL) < 0)
+        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;
+
+    ret = 0;
+
+cleanup:
+    VIR_FREE(pidfile);
+    for (i = 0; argv[i]; i++)
+        VIR_FREE(argv[i]);
+    VIR_FREE(argv);
+
+    return ret;
+}
+
+static int
+networkAddMasqueradingIptablesRules(virConnectPtr conn,
+                      struct network_driver *driver,
+                      virNetworkObjPtr network) {
+    int err;
+    /* allow forwarding packets from the bridge interface */
+    if ((err = iptablesAddForwardAllowOut(driver->iptables,
+                                          network->def->network,
+                                          network->def->bridge,
+                                          network->def->forwardDev))) {
+        virReportSystemError(conn, err,
+                             _("failed to add iptables rule to allow forwarding from '%s'"),
+                             network->def->bridge);
+        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))) {
+        virReportSystemError(conn, err,
+                             _("failed to add iptables rule to allow forwarding to '%s'"),
+                             network->def->bridge);
+        goto masqerr2;
+    }
+
+    /* enable masquerading */
+    if ((err = iptablesAddForwardMasquerade(driver->iptables,
+                                            network->def->network,
+                                            network->def->forwardDev))) {
+        virReportSystemError(conn, err,
+                             _("failed to add iptables rule to enable masquerading to '%s'\n"),
+                             network->def->forwardDev ? network->def->forwardDev : NULL);
+        goto masqerr3;
+    }
+
+    return 1;
+
+ 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
+networkAddRoutingIptablesRules(virConnectPtr conn,
+                      struct network_driver *driver,
+                      virNetworkObjPtr network) {
+    int err;
+    /* allow routing packets from the bridge interface */
+    if ((err = iptablesAddForwardAllowOut(driver->iptables,
+                                          network->def->network,
+                                          network->def->bridge,
+                                          network->def->forwardDev))) {
+        virReportSystemError(conn, err,
+                             _("failed to add iptables rule to allow routing from '%s'"),
+                             network->def->bridge);
+        goto routeerr1;
+    }
+
+    /* allow routing packets to the bridge interface */
+    if ((err = iptablesAddForwardAllowIn(driver->iptables,
+                                         network->def->network,
+                                         network->def->bridge,
+                                         network->def->forwardDev))) {
+        virReportSystemError(conn, err,
+                             _("failed to add iptables rule to allow routing to '%s'"),
+                             network->def->bridge);
+        goto routeerr2;
+    }
+
+    return 1;
+
+
+ routeerr2:
+    iptablesRemoveForwardAllowOut(driver->iptables,
+                                  network->def->network,
+                                  network->def->bridge,
+                                  network->def->forwardDev);
+ routeerr1:
+    return 0;
+}
+
+static int
+networkAddIptablesRules(virConnectPtr conn,
+                      struct network_driver *driver,
+                      virNetworkObjPtr network) {
+    int err;
+
+    /* allow DHCP requests through to dnsmasq */
+    if ((err = iptablesAddTcpInput(driver->iptables, network->def->bridge, 67))) {
+        virReportSystemError(conn, err,
+                             _("failed to add iptables rule to allow DHCP requests from '%s'"),
+                             network->def->bridge);
+        goto err1;
+    }
+
+    if ((err = iptablesAddUdpInput(driver->iptables, network->def->bridge, 67))) {
+        virReportSystemError(conn, err,
+                             _("failed to add iptables rule to allow DHCP requests from '%s'"),
+                             network->def->bridge);
+        goto err2;
+    }
+
+    /* allow DNS requests through to dnsmasq */
+    if ((err = iptablesAddTcpInput(driver->iptables, network->def->bridge, 53))) {
+        virReportSystemError(conn, err,
+                             _("failed to add iptables rule to allow DNS requests from '%s'"),
+                             network->def->bridge);
+        goto err3;
+    }
+
+    if ((err = iptablesAddUdpInput(driver->iptables, network->def->bridge, 53))) {
+        virReportSystemError(conn, err,
+                             _("failed to add iptables rule to allow DNS requests from '%s'"),
+                             network->def->bridge);
+        goto err4;
+    }
+
+
+    /* Catch all rules to block forwarding to/from bridges */
+
+    if ((err = iptablesAddForwardRejectOut(driver->iptables, network->def->bridge))) {
+        virReportSystemError(conn, err,
+                             _("failed to add iptables rule to block outbound traffic from '%s'"),
+                             network->def->bridge);
+        goto err5;
+    }
+
+    if ((err = iptablesAddForwardRejectIn(driver->iptables, network->def->bridge))) {
+        virReportSystemError(conn, err,
+                             _("failed to add iptables rule to block inbound traffic to '%s'"),
+                             network->def->bridge);
+        goto err6;
+    }
+
+    /* Allow traffic between guests on the same bridge */
+    if ((err = iptablesAddForwardAllowCross(driver->iptables, network->def->bridge))) {
+        virReportSystemError(conn, err,
+                             _("failed to add iptables rule to allow cross bridge traffic on '%s'"),
+                             network->def->bridge);
+        goto err7;
+    }
+
+
+    /* If masquerading is enabled, set up the rules*/
+    if (network->def->forwardType == VIR_NETWORK_FORWARD_NAT &&
+        !networkAddMasqueradingIptablesRules(conn, driver, network))
+        goto err8;
+    /* else if routing is enabled, set up the rules*/
+    else if (network->def->forwardType == VIR_NETWORK_FORWARD_ROUTE &&
+             !networkAddRoutingIptablesRules(conn, driver, network))
+        goto err8;
+
+    iptablesSaveRules(driver->iptables);
+
+    return 1;
+
+ err8:
+    iptablesRemoveForwardAllowCross(driver->iptables,
+                                    network->def->bridge);
+ err7:
+    iptablesRemoveForwardRejectIn(driver->iptables,
+                                  network->def->bridge);
+ err6:
+    iptablesRemoveForwardRejectOut(driver->iptables,
+                                   network->def->bridge);
+ err5:
+    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) {
+    if (network->def->forwardType != VIR_NETWORK_FORWARD_NONE) {
+        iptablesRemoveForwardMasquerade(driver->iptables,
+                                        network->def->network,
+                                        network->def->forwardDev);
+
+        if (network->def->forwardType == VIR_NETWORK_FORWARD_NAT)
+            iptablesRemoveForwardAllowRelatedIn(driver->iptables,
+                                                network->def->network,
+                                                network->def->bridge,
+                                                network->def->forwardDev);
+        else if (network->def->forwardType == VIR_NETWORK_FORWARD_ROUTE)
+            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);
+    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);
+    iptablesSaveRules(driver->iptables);
+}
+
+/* Enable IP Forwarding. Return 0 for success, -1 for failure. */
+static int
+networkEnableIpForwarding(void)
+{
+    return virFileWriteStr("/proc/sys/net/ipv4/ip_forward", "1\n");
+}
+
+#define SYSCTL_PATH "/proc/sys"
+
+static int networkDisableIPV6(virConnectPtr conn,
+                              virNetworkObjPtr network)
+{
+    char *field = NULL;
+    int ret = -1;
+
+    if (virAsprintf(&field, SYSCTL_PATH "/net/ipv6/conf/%s/disable_ipv6", network->def->bridge) < 0) {
+        virReportOOMError(conn);
+        goto cleanup;
+    }
+
+    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;
+    }
+
+    if (virFileWriteStr(field, "1") < 0) {
+        virReportSystemError(conn, errno,
+                             _("cannot enable %s"), field);
+        goto cleanup;
+    }
+    VIR_FREE(field);
+
+    if (virAsprintf(&field, SYSCTL_PATH "/net/ipv6/conf/%s/accept_ra", network->def->bridge) < 0) {
+        virReportOOMError(conn);
+        goto cleanup;
+    }
+
+    if (virFileWriteStr(field, "0") < 0) {
+        virReportSystemError(conn, errno,
+                             _("cannot disable %s"), field);
+        goto cleanup;
+    }
+    VIR_FREE(field);
+
+    if (virAsprintf(&field, SYSCTL_PATH "/net/ipv6/conf/%s/autoconf", network->def->bridge) < 0) {
+        virReportOOMError(conn);
+        goto cleanup;
+    }
+
+    if (virFileWriteStr(field, "1") < 0) {
+        virReportSystemError(conn, errno,
+                             _("cannot enable %s"), field);
+        goto cleanup;
+    }
+
+    ret = 0;
+cleanup:
+    VIR_FREE(field);
+    return ret;
+}
+
+static int networkStartNetworkDaemon(virConnectPtr conn,
+                                   struct network_driver *driver,
+                                   virNetworkObjPtr network) {
+    int err;
+
+    if (virNetworkIsActive(network)) {
+        networkReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+                         "%s", _("network is already active"));
+        return -1;
+    }
+
+    if ((err = brAddBridge(driver->brctl, network->def->bridge))) {
+        virReportSystemError(conn, err,
+                             _("cannot create bridge '%s'"),
+                             network->def->bridge);
+        return -1;
+    }
+
+    if (networkDisableIPV6(conn, network) < 0)
+        goto err_delbr;
+
+    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))) {
+        virReportSystemError(conn, err,
+                             _("cannot set IP address on bridge '%s' to '%s'"),
+                             network->def->bridge, network->def->ipAddress);
+        goto err_delbr;
+    }
+
+    if (network->def->netmask &&
+        (err = brSetInetNetmask(driver->brctl, network->def->bridge, network->def->netmask))) {
+        virReportSystemError(conn, err,
+                             _("cannot set netmask on bridge '%s' to '%s'"),
+                             network->def->bridge, network->def->netmask);
+        goto err_delbr;
+    }
+
+    if ((err = brSetInterfaceUp(driver->brctl, network->def->bridge, 1))) {
+        virReportSystemError(conn, err,
+                             _("failed to bring the bridge '%s' up"),
+                             network->def->bridge);
+        goto err_delbr;
+    }
+
+    if (!networkAddIptablesRules(conn, driver, network))
+        goto err_delbr1;
+
+    if (network->def->forwardType != VIR_NETWORK_FORWARD_NONE &&
+        networkEnableIpForwarding() < 0) {
+        virReportSystemError(conn, errno, "%s",
+                             _("failed to enable IP forwarding"));
+        goto err_delbr2;
+    }
+
+    if ((network->def->ipAddress ||
+         network->def->nranges) &&
+        dhcpStartDhcpDaemon(conn, network) < 0)
+        goto err_delbr2;
+
+
+    /* Persist the live configuration now we have bridge info  */
+    if (virNetworkSaveConfig(conn, NETWORK_STATE_DIR, network->def) < 0) {
+        goto err_kill;
+    }
+
+    network->active = 1;
+
+    return 0;
+
+ err_kill:
+    if (network->dnsmasqPid > 0) {
+        kill(network->dnsmasqPid, SIGTERM);
+        network->dnsmasqPid = -1;
+    }
+
+ err_delbr2:
+    networkRemoveIptablesRules(driver, network);
+
+ err_delbr1:
+    if ((err = brSetInterfaceUp(driver->brctl, network->def->bridge, 0))) {
+        char ebuf[1024];
+        VIR_WARN(_("Failed to bring down bridge '%s' : %s\n"),
+                 network->def->bridge, virStrerror(err, ebuf, sizeof ebuf));
+    }
+
+ err_delbr:
+    if ((err = brDeleteBridge(driver->brctl, network->def->bridge))) {
+        char ebuf[1024];
+        VIR_WARN(_("Failed to delete bridge '%s' : %s\n"),
+                 network->def->bridge, virStrerror(err, ebuf, sizeof ebuf));
+    }
+
+    return -1;
+}
+
+
+static int networkShutdownNetworkDaemon(virConnectPtr conn,
+                                        struct network_driver *driver,
+                                        virNetworkObjPtr network) {
+    int err;
+    char *stateFile;
+
+    VIR_INFO(_("Shutting down network '%s'\n"), network->def->name);
+
+    if (!virNetworkIsActive(network))
+        return 0;
+
+    stateFile = virNetworkConfigFile(conn, NETWORK_STATE_DIR, network->def->name);
+    if (!stateFile)
+        return -1;
+
+    unlink(stateFile);
+    VIR_FREE(stateFile);
+
+    if (network->dnsmasqPid > 0)
+        kill(network->dnsmasqPid, SIGTERM);
+
+    networkRemoveIptablesRules(driver, network);
+
+    char ebuf[1024];
+    if ((err = brSetInterfaceUp(driver->brctl, network->def->bridge, 0))) {
+        VIR_WARN(_("Failed to bring down bridge '%s' : %s\n"),
+                 network->def->bridge, virStrerror(err, ebuf, sizeof ebuf));
+    }
+
+    if ((err = brDeleteBridge(driver->brctl, network->def->bridge))) {
+        VIR_WARN(_("Failed to delete bridge '%s' : %s\n"),
+                 network->def->bridge, virStrerror(err, ebuf, sizeof ebuf));
+    }
+
+    /* See if its still alive and really really kill it */
+    if (network->dnsmasqPid > 0 &&
+        (kill(network->dnsmasqPid, 0) == 0))
+        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;
+}
+
+
+static virNetworkPtr networkLookupByUUID(virConnectPtr conn,
+                                         const unsigned char *uuid) {
+    struct network_driver *driver = conn->networkPrivateData;
+    virNetworkObjPtr network;
+    virNetworkPtr ret = NULL;
+
+    networkDriverLock(driver);
+    network = virNetworkFindByUUID(&driver->networks, uuid);
+    networkDriverUnlock(driver);
+    if (!network) {
+        networkReportError(conn, NULL, NULL, VIR_ERR_NO_NETWORK,
+                         "%s", _("no network with matching uuid"));
+        goto cleanup;
+    }
+
+    ret = virGetNetwork(conn, network->def->name, network->def->uuid);
+
+cleanup:
+    if (network)
+        virNetworkObjUnlock(network);
+    return ret;
+}
+
+static virNetworkPtr networkLookupByName(virConnectPtr conn,
+                                         const char *name) {
+    struct network_driver *driver = conn->networkPrivateData;
+    virNetworkObjPtr network;
+    virNetworkPtr ret = NULL;
+
+    networkDriverLock(driver);
+    network = virNetworkFindByName(&driver->networks, name);
+    networkDriverUnlock(driver);
+    if (!network) {
+        networkReportError(conn, NULL, NULL, VIR_ERR_NO_NETWORK,
+                         _("no network with matching name '%s'"), name);
+        goto cleanup;
+    }
+
+    ret = virGetNetwork(conn, network->def->name, network->def->uuid);
+
+cleanup:
+    if (network)
+        virNetworkObjUnlock(network);
+    return ret;
+}
+
+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) {
+    int nactive = 0, i;
+    struct network_driver *driver = conn->networkPrivateData;
+
+    networkDriverLock(driver);
+    for (i = 0 ; i < driver->networks.count ; i++) {
+        virNetworkObjLock(driver->networks.objs[i]);
+        if (virNetworkIsActive(driver->networks.objs[i]))
+            nactive++;
+        virNetworkObjUnlock(driver->networks.objs[i]);
+    }
+    networkDriverUnlock(driver);
+
+    return nactive;
+}
+
+static int networkListNetworks(virConnectPtr conn, char **const names, int nnames) {
+    struct network_driver *driver = conn->networkPrivateData;
+    int got = 0, i;
+
+    networkDriverLock(driver);
+    for (i = 0 ; i < driver->networks.count && got < nnames ; i++) {
+        virNetworkObjLock(driver->networks.objs[i]);
+        if (virNetworkIsActive(driver->networks.objs[i])) {
+            if (!(names[got] = strdup(driver->networks.objs[i]->def->name))) {
+                virNetworkObjUnlock(driver->networks.objs[i]);
+                virReportOOMError(conn);
+                goto cleanup;
+            }
+            got++;
+        }
+        virNetworkObjUnlock(driver->networks.objs[i]);
+    }
+    networkDriverUnlock(driver);
+
+    return got;
+
+ cleanup:
+    networkDriverUnlock(driver);
+    for (i = 0 ; i < got ; i++)
+        VIR_FREE(names[i]);
+    return -1;
+}
+
+static int networkNumDefinedNetworks(virConnectPtr conn) {
+    int ninactive = 0, i;
+    struct network_driver *driver = conn->networkPrivateData;
+
+    networkDriverLock(driver);
+    for (i = 0 ; i < driver->networks.count ; i++) {
+        virNetworkObjLock(driver->networks.objs[i]);
+        if (!virNetworkIsActive(driver->networks.objs[i]))
+            ninactive++;
+        virNetworkObjUnlock(driver->networks.objs[i]);
+    }
+    networkDriverUnlock(driver);
+
+    return ninactive;
+}
+
+static int networkListDefinedNetworks(virConnectPtr conn, char **const names, int nnames) {
+    struct network_driver *driver = conn->networkPrivateData;
+    int got = 0, i;
+
+    networkDriverLock(driver);
+    for (i = 0 ; i < driver->networks.count && got < nnames ; i++) {
+        virNetworkObjLock(driver->networks.objs[i]);
+        if (!virNetworkIsActive(driver->networks.objs[i])) {
+            if (!(names[got] = strdup(driver->networks.objs[i]->def->name))) {
+                virNetworkObjUnlock(driver->networks.objs[i]);
+                virReportOOMError(conn);
+                goto cleanup;
+            }
+            got++;
+        }
+        virNetworkObjUnlock(driver->networks.objs[i]);
+    }
+    networkDriverUnlock(driver);
+    return got;
+
+ cleanup:
+    networkDriverUnlock(driver);
+    for (i = 0 ; i < got ; i++)
+        VIR_FREE(names[i]);
+    return -1;
+}
+
+static virNetworkPtr networkCreate(virConnectPtr conn, const char *xml) {
+    struct network_driver *driver = conn->networkPrivateData;
+    virNetworkDefPtr def;
+    virNetworkObjPtr network = NULL;
+    virNetworkPtr ret = NULL;
+
+    networkDriverLock(driver);
+
+    if (!(def = virNetworkDefParseString(conn, xml)))
+        goto cleanup;
+
+    if (virNetworkSetBridgeName(conn, &driver->networks, def, 1))
+        goto cleanup;
+
+    if (!(network = virNetworkAssignDef(conn,
+                                        &driver->networks,
+                                        def)))
+        goto cleanup;
+    def = NULL;
+
+    if (networkStartNetworkDaemon(conn, driver, network) < 0) {
+        virNetworkRemoveInactive(&driver->networks,
+                                 network);
+        network = NULL;
+        goto cleanup;
+    }
+
+    ret = virGetNetwork(conn, network->def->name, network->def->uuid);
+
+cleanup:
+    virNetworkDefFree(def);
+    if (network)
+        virNetworkObjUnlock(network);
+    networkDriverUnlock(driver);
+    return ret;
+}
+
+static virNetworkPtr networkDefine(virConnectPtr conn, const char *xml) {
+    struct network_driver *driver = conn->networkPrivateData;
+    virNetworkDefPtr def;
+    virNetworkObjPtr network = NULL;
+    virNetworkPtr ret = NULL;
+
+    networkDriverLock(driver);
+
+    if (!(def = virNetworkDefParseString(conn, xml)))
+        goto cleanup;
+
+    if (virNetworkSetBridgeName(conn, &driver->networks, def, 1))
+        goto cleanup;
+
+    if (!(network = virNetworkAssignDef(conn,
+                                        &driver->networks,
+                                        def)))
+        goto cleanup;
+    def = NULL;
+
+    network->persistent = 1;
+
+    if (virNetworkSaveConfig(conn,
+                             driver->networkConfigDir,
+                             network->newDef ? network->newDef : network->def) < 0) {
+        virNetworkRemoveInactive(&driver->networks,
+                                 network);
+        network = NULL;
+        goto cleanup;
+    }
+
+    ret = virGetNetwork(conn, network->def->name, network->def->uuid);
+
+cleanup:
+    virNetworkDefFree(def);
+    if (network)
+        virNetworkObjUnlock(network);
+    networkDriverUnlock(driver);
+    return ret;
+}
+
+static int networkUndefine(virNetworkPtr net) {
+    struct network_driver *driver = net->conn->networkPrivateData;
+    virNetworkObjPtr network = NULL;
+    int ret = -1;
+
+    networkDriverLock(driver);
+
+    network = virNetworkFindByUUID(&driver->networks, net->uuid);
+    if (!network) {
+        networkReportError(net->conn, NULL, net, VIR_ERR_INVALID_DOMAIN,
+                           "%s", _("no network with matching uuid"));
+        goto cleanup;
+    }
+
+    if (virNetworkIsActive(network)) {
+        networkReportError(net->conn, NULL, net, VIR_ERR_INTERNAL_ERROR,
+                           "%s", _("network is still active"));
+        goto cleanup;
+    }
+
+    if (virNetworkDeleteConfig(net->conn,
+                               driver->networkConfigDir,
+                               driver->networkAutostartDir,
+                               network) < 0)
+        goto cleanup;
+
+    virNetworkRemoveInactive(&driver->networks,
+                             network);
+    network = NULL;
+    ret = 0;
+
+cleanup:
+    if (network)
+        virNetworkObjUnlock(network);
+    networkDriverUnlock(driver);
+    return ret;
+}
+
+static int networkStart(virNetworkPtr net) {
+    struct network_driver *driver = net->conn->networkPrivateData;
+    virNetworkObjPtr network;
+    int ret = -1;
+
+    networkDriverLock(driver);
+    network = virNetworkFindByUUID(&driver->networks, net->uuid);
+
+    if (!network) {
+        networkReportError(net->conn, NULL, net, VIR_ERR_INVALID_NETWORK,
+                           "%s", _("no network with matching uuid"));
+        goto cleanup;
+    }
+
+    ret = networkStartNetworkDaemon(net->conn, driver, network);
+
+cleanup:
+    if (network)
+        virNetworkObjUnlock(network);
+    networkDriverUnlock(driver);
+    return ret;
+}
+
+static int networkDestroy(virNetworkPtr net) {
+    struct network_driver *driver = net->conn->networkPrivateData;
+    virNetworkObjPtr network;
+    int ret = -1;
+
+    networkDriverLock(driver);
+    network = virNetworkFindByUUID(&driver->networks, net->uuid);
+
+    if (!network) {
+        networkReportError(net->conn, NULL, net, VIR_ERR_INVALID_NETWORK,
+                           "%s", _("no network with matching uuid"));
+        goto cleanup;
+    }
+
+    if (!virNetworkIsActive(network)) {
+        networkReportError(net->conn, NULL, net, VIR_ERR_INTERNAL_ERROR,
+                           "%s", _("network is not active"));
+        goto cleanup;
+    }
+
+    ret = networkShutdownNetworkDaemon(net->conn, driver, network);
+    if (!network->persistent) {
+        virNetworkRemoveInactive(&driver->networks,
+                                 network);
+        network = NULL;
+    }
+
+cleanup:
+    if (network)
+        virNetworkObjUnlock(network);
+    networkDriverUnlock(driver);
+    return ret;
+}
+
+static char *networkDumpXML(virNetworkPtr net, int flags ATTRIBUTE_UNUSED) {
+    struct network_driver *driver = net->conn->networkPrivateData;
+    virNetworkObjPtr network;
+    char *ret = NULL;
+
+    networkDriverLock(driver);
+    network = virNetworkFindByUUID(&driver->networks, net->uuid);
+    networkDriverUnlock(driver);
+
+    if (!network) {
+        networkReportError(net->conn, NULL, net, VIR_ERR_INVALID_NETWORK,
+                           "%s", _("no network with matching uuid"));
+        goto cleanup;
+    }
+
+    ret = virNetworkDefFormat(net->conn, network->def);
+
+cleanup:
+    if (network)
+        virNetworkObjUnlock(network);
+    return ret;
+}
+
+static char *networkGetBridgeName(virNetworkPtr net) {
+    struct network_driver *driver = net->conn->networkPrivateData;
+    virNetworkObjPtr network;
+    char *bridge = NULL;
+
+    networkDriverLock(driver);
+    network = virNetworkFindByUUID(&driver->networks, net->uuid);
+    networkDriverUnlock(driver);
+
+    if (!network) {
+        networkReportError(net->conn, NULL, net, VIR_ERR_INVALID_NETWORK,
+                           "%s", _("no network with matching id"));
+        goto cleanup;
+    }
+
+    if (!(network->def->bridge)) {
+        networkReportError(net->conn, NULL, net, VIR_ERR_INTERNAL_ERROR,
+                           _("network '%s' does not have a bridge name."),
+                           network->def->name);
+        goto cleanup;
+    }
+
+    bridge = strdup(network->def->bridge);
+    if (!bridge)
+        virReportOOMError(net->conn);
+
+cleanup:
+    if (network)
+        virNetworkObjUnlock(network);
+    return bridge;
+}
+
+static int networkGetAutostart(virNetworkPtr net,
+                             int *autostart) {
+    struct network_driver *driver = net->conn->networkPrivateData;
+    virNetworkObjPtr network;
+    int ret = -1;
+
+    networkDriverLock(driver);
+    network = virNetworkFindByUUID(&driver->networks, net->uuid);
+    networkDriverUnlock(driver);
+    if (!network) {
+        networkReportError(net->conn, NULL, net, VIR_ERR_INVALID_NETWORK,
+                         "%s", _("no network with matching uuid"));
+        goto cleanup;
+    }
+
+    *autostart = network->autostart;
+    ret = 0;
+
+cleanup:
+    if (network)
+        virNetworkObjUnlock(network);
+    return ret;
+}
+
+static int networkSetAutostart(virNetworkPtr net,
+                               int autostart) {
+    struct network_driver *driver = net->conn->networkPrivateData;
+    virNetworkObjPtr network;
+    char *configFile = NULL, *autostartLink = NULL;
+    int ret = -1;
+
+    networkDriverLock(driver);
+    network = virNetworkFindByUUID(&driver->networks, net->uuid);
+
+    if (!network) {
+        networkReportError(net->conn, NULL, net, VIR_ERR_INVALID_NETWORK,
+                         "%s", _("no network with matching uuid"));
+        goto cleanup;
+    }
+
+    if (!network->persistent) {
+        networkReportError(net->conn, NULL, net, VIR_ERR_INTERNAL_ERROR,
+                         "%s", _("cannot set autostart for transient network"));
+        goto cleanup;
+    }
+
+    autostart = (autostart != 0);
+
+    if (network->autostart != autostart) {
+        if ((configFile = virNetworkConfigFile(net->conn, driver->networkConfigDir, network->def->name)) == NULL)
+            goto cleanup;
+        if ((autostartLink = virNetworkConfigFile(net->conn, driver->networkAutostartDir, network->def->name)) == NULL)
+            goto cleanup;
+
+        if (autostart) {
+            if (virFileMakePath(driver->networkAutostartDir)) {
+                virReportSystemError(net->conn, errno,
+                                     _("cannot create autostart directory '%s'"),
+                                     driver->networkAutostartDir);
+                goto cleanup;
+            }
+
+            if (symlink(configFile, autostartLink) < 0) {
+                virReportSystemError(net->conn, errno,
+                                     _("Failed to create symlink '%s' to '%s'"),
+                                     autostartLink, configFile);
+                goto cleanup;
+            }
+        } else {
+            if (unlink(autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) {
+                virReportSystemError(net->conn, errno,
+                                     _("Failed to delete symlink '%s'"),
+                                     autostartLink);
+                goto cleanup;
+            }
+        }
+
+        network->autostart = autostart;
+    }
+    ret = 0;
+
+cleanup:
+    VIR_FREE(configFile);
+    VIR_FREE(autostartLink);
+    if (network)
+        virNetworkObjUnlock(network);
+    networkDriverUnlock(driver);
+    return ret;
+}
+
+
+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 */
+};
+
+static virStateDriver networkStateDriver = {
+    networkStartup,
+    networkShutdown,
+    networkReload,
+    networkActive,
+};
+
+int networkRegister(void) {
+    virRegisterNetworkDriver(&networkDriver);
+    virRegisterStateDriver(&networkStateDriver);
+    return 0;
+}
diff --git a/src/network/bridge_driver.h b/src/network/bridge_driver.h
new file mode 100644 (file)
index 0000000..5951833
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * network_driver.h: core driver methods for managing networks
+ *
+ * Copyright (C) 2006, 2007 Red Hat, Inc.
+ * 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>
+ */
+
+
+#ifndef __VIR_NETWORK__DRIVER_H
+#define __VIR_NETWORK__DRIVER_H
+
+#include <config.h>
+
+#include "internal.h"
+
+int networkRegister(void);
+
+#endif /* __VIR_NETWORK__DRIVER_H */
diff --git a/src/network_driver.c b/src/network_driver.c
deleted file mode 100644 (file)
index 49855bf..0000000
+++ /dev/null
@@ -1,1499 +0,0 @@
-/*
- * driver.c: core driver methods for managing qemu guests
- *
- * Copyright (C) 2006-2009 Red Hat, Inc.
- * 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 <strings.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>
-
-#include "virterror_internal.h"
-#include "datatypes.h"
-#include "network_driver.h"
-#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"
-#include "logging.h"
-
-#define NETWORK_PID_DIR LOCAL_STATE_DIR "/run/libvirt/network"
-#define NETWORK_STATE_DIR LOCAL_STATE_DIR "/lib/libvirt/network"
-
-#define VIR_FROM_THIS VIR_FROM_NETWORK
-
-/* Main driver state */
-struct network_driver {
-    virMutex lock;
-
-    virNetworkObjList networks;
-
-    iptablesContext *iptables;
-    brControl *brctl;
-    char *networkConfigDir;
-    char *networkAutostartDir;
-    char *logDir;
-};
-
-
-static void networkDriverLock(struct network_driver *driver)
-{
-    virMutexLock(&driver->lock);
-}
-static void networkDriverUnlock(struct network_driver *driver)
-{
-    virMutexUnlock(&driver->lock);
-}
-
-static int networkShutdown(void);
-
-static int networkStartNetworkDaemon(virConnectPtr conn,
-                                   struct network_driver *driver,
-                                   virNetworkObjPtr network);
-
-static int networkShutdownNetworkDaemon(virConnectPtr conn,
-                                      struct network_driver *driver,
-                                      virNetworkObjPtr network);
-
-static struct network_driver *driverState = NULL;
-
-
-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);
-
-        if ((config = virNetworkConfigFile(NULL,
-                                           NETWORK_STATE_DIR,
-                                           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 */
-        tmp = virNetworkDefParseFile(NULL, config);
-        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;
-
-            /* Finally try and read dnsmasq pid if any */
-            if ((obj->def->ipAddress ||
-                 obj->def->nranges) &&
-                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;
-
-                virAsprintf(&pidpath, "/proc/%d/exe", obj->dnsmasqPid);
-                if (virFileLinkPointsTo(pidpath, DNSMASQ) == 0)
-                    obj->dnsmasqPid = -1;
-                VIR_FREE(pidpath);
-#endif
-            }
-        }
-
-        virNetworkObjUnlock(obj);
-    }
-}
-
-
-static void
-networkAutostartConfigs(struct network_driver *driver) {
-    unsigned int i;
-
-    for (i = 0 ; i < driver->networks.count ; i++) {
-        virNetworkObjLock(driver->networks.objs[i]);
-        if (driver->networks.objs[i]->autostart &&
-            !virNetworkIsActive(driver->networks.objs[i]) &&
-            networkStartNetworkDaemon(NULL, driver, driver->networks.objs[i]) < 0) {
-            /* failed to start but already logged */
-        }
-        virNetworkObjUnlock(driver->networks.objs[i]);
-    }
-}
-
-/**
- * networkStartup:
- *
- * Initialization function for the QEmu daemon
- */
-static int
-networkStartup(int privileged) {
-    uid_t uid = geteuid();
-    char *base = NULL;
-    int err;
-
-    if (VIR_ALLOC(driverState) < 0)
-        goto error;
-
-    if (virMutexInit(&driverState->lock) < 0) {
-        VIR_FREE(driverState);
-        goto error;
-    }
-    networkDriverLock(driverState);
-
-    if (privileged) {
-        if (virAsprintf(&driverState->logDir,
-                        "%s/log/libvirt/qemu", LOCAL_STATE_DIR) == -1)
-            goto out_of_memory;
-
-        if ((base = strdup (SYSCONF_DIR "/libvirt")) == NULL)
-            goto out_of_memory;
-    } else {
-        char *userdir = virGetUserDirectory(NULL, uid);
-
-        if (!userdir)
-            goto error;
-
-        if (virAsprintf(&driverState->logDir,
-                        "%s/.libvirt/qemu/log", userdir) == -1) {
-            VIR_FREE(userdir);
-            goto out_of_memory;
-        }
-
-        if (virAsprintf(&base, "%s/.libvirt", userdir) == -1) {
-            VIR_FREE(userdir);
-            goto out_of_memory;
-        }
-        VIR_FREE(userdir);
-    }
-
-    /* Configuration paths are either ~/.libvirt/qemu/... (session) or
-     * /etc/libvirt/qemu/... (system).
-     */
-    if (virAsprintf(&driverState->networkConfigDir, "%s/qemu/networks", base) == -1)
-        goto out_of_memory;
-
-    if (virAsprintf(&driverState->networkAutostartDir, "%s/qemu/networks/autostart",
-                    base) == -1)
-        goto out_of_memory;
-
-    VIR_FREE(base);
-
-    if ((err = brInit(&driverState->brctl))) {
-        virReportSystemError(NULL, err, "%s",
-                             _("cannot initialize bridge support"));
-        goto error;
-    }
-
-    if (!(driverState->iptables = iptablesContextNew())) {
-        goto out_of_memory;
-    }
-
-
-    if (virNetworkLoadAllConfigs(NULL,
-                                 &driverState->networks,
-                                 driverState->networkConfigDir,
-                                 driverState->networkAutostartDir) < 0)
-        goto error;
-
-    networkFindActiveConfigs(driverState);
-    networkAutostartConfigs(driverState);
-
-    networkDriverUnlock(driverState);
-
-    return 0;
-
-out_of_memory:
-    virReportOOMError(NULL);
-
-error:
-    if (driverState)
-        networkDriverUnlock(driverState);
-
-    VIR_FREE(base);
-    networkShutdown();
-    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) {
-    if (!driverState)
-        return 0;
-
-    networkDriverLock(driverState);
-    virNetworkLoadAllConfigs(NULL,
-                             &driverState->networks,
-                             driverState->networkConfigDir,
-                             driverState->networkAutostartDir);
-
-     if (driverState->iptables) {
-        VIR_INFO0(_("Reloading iptables rules\n"));
-        iptablesReloadRules(driverState->iptables);
-    }
-
-    networkAutostartConfigs(driverState);
-    networkDriverUnlock(driverState);
-    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) {
-    unsigned int i;
-    int active = 0;
-
-    if (!driverState)
-        return 0;
-
-    networkDriverLock(driverState);
-    for (i = 0 ; i < driverState->networks.count ; i++) {
-        virNetworkObjPtr net = driverState->networks.objs[i];
-        virNetworkObjLock(net);
-        if (virNetworkIsActive(net))
-            active = 1;
-        virNetworkObjUnlock(net);
-    }
-    networkDriverUnlock(driverState);
-    return active;
-}
-
-/**
- * networkShutdown:
- *
- * Shutdown the QEmu daemon, it will stop all active domains and networks
- */
-static int
-networkShutdown(void) {
-    if (!driverState)
-        return -1;
-
-    networkDriverLock(driverState);
-
-    /* free inactive networks */
-    virNetworkObjListFree(&driverState->networks);
-
-    VIR_FREE(driverState->logDir);
-    VIR_FREE(driverState->networkConfigDir);
-    VIR_FREE(driverState->networkAutostartDir);
-
-    if (driverState->brctl)
-        brShutdown(driverState->brctl);
-    if (driverState->iptables)
-        iptablesContextFree(driverState->iptables);
-
-    networkDriverUnlock(driverState);
-    virMutexDestroy(&driverState->lock);
-
-    VIR_FREE(driverState);
-
-    return 0;
-}
-
-
-static int
-networkBuildDnsmasqArgv(virConnectPtr conn,
-                        virNetworkObjPtr network,
-                        const char *pidfile,
-                        const char ***argv) {
-    int i, len, r;
-    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
-     */
-
-    len =
-        1 + /* dnsmasq */
-        1 + /* --strict-order */
-        1 + /* --bind-interfaces */
-        (network->def->domain?2:0) + /* --domain name */
-        2 + /* --pid-file /var/run/libvirt/network/$NAME.pid */
-        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 */
-        /*  --dhcp-host 01:23:45:67:89:0a,hostname,10.0.0.3 */
-        (2 * network->def->nhosts) +
-        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)
-
-#define APPEND_ARG_LIT(v, n, s) \
-        (v)[(n)] = s
-
-    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);
-    }
-
-    if (virAsprintf(&pidfileArg, "--pid-file=%s", pidfile) < 0)
-        goto no_memory;
-    APPEND_ARG_LIT(*argv, i++, pidfileArg);
-
-    APPEND_ARG(*argv, i++, "--conf-file=");
-    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);
-    }
-
-    for (r = 0 ; r < network->def->nhosts ; r++) {
-        virNetworkDHCPHostDefPtr host = &(network->def->hosts[r]);
-        if ((host->mac) && (host->name)) {
-            snprintf(buf, sizeof(buf), "%s,%s,%s",
-                     host->mac, host->name, host->ip);
-        } else if (host->mac) {
-            snprintf(buf, sizeof(buf), "%s,%s",
-                     host->mac, host->ip);
-        } else if (host->name) {
-            snprintf(buf, sizeof(buf), "%s,%s",
-                     host->name, host->ip);
-        } else
-            continue;
-
-        APPEND_ARG(*argv, i++, "--dhcp-host");
-        APPEND_ARG(*argv, i++, buf);
-    }
-
-#undef APPEND_ARG
-
-    return 0;
-
- no_memory:
-    if (argv) {
-        for (i = 0; (*argv)[i]; i++)
-            VIR_FREE((*argv)[i]);
-        VIR_FREE(*argv);
-    }
-    virReportOOMError(conn);
-    return -1;
-}
-
-
-static int
-dhcpStartDhcpDaemon(virConnectPtr conn,
-                    virNetworkObjPtr network)
-{
-    const char **argv;
-    char *pidfile;
-    int ret = -1, i, err;
-
-    network->dnsmasqPid = -1;
-
-    if (network->def->ipAddress == NULL) {
-        networkReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                         "%s", _("cannot start dhcp daemon without IP address for server"));
-        return -1;
-    }
-
-    if ((err = virFileMakePath(NETWORK_PID_DIR)) < 0) {
-        virReportSystemError(conn, err,
-                             _("cannot create directory %s"),
-                             NETWORK_PID_DIR);
-        return -1;
-    }
-    if ((err = virFileMakePath(NETWORK_STATE_DIR)) < 0) {
-        virReportSystemError(conn, err,
-                             _("cannot create directory %s"),
-                             NETWORK_STATE_DIR);
-        return -1;
-    }
-
-    if (!(pidfile = virFilePid(NETWORK_PID_DIR, network->def->name))) {
-        virReportOOMError(conn);
-        return -1;
-    }
-
-    argv = NULL;
-    if (networkBuildDnsmasqArgv(conn, network, pidfile, &argv) < 0) {
-        VIR_FREE(pidfile);
-        return -1;
-    }
-
-    if (virRun(conn, argv, NULL) < 0)
-        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;
-
-    ret = 0;
-
-cleanup:
-    VIR_FREE(pidfile);
-    for (i = 0; argv[i]; i++)
-        VIR_FREE(argv[i]);
-    VIR_FREE(argv);
-
-    return ret;
-}
-
-static int
-networkAddMasqueradingIptablesRules(virConnectPtr conn,
-                      struct network_driver *driver,
-                      virNetworkObjPtr network) {
-    int err;
-    /* allow forwarding packets from the bridge interface */
-    if ((err = iptablesAddForwardAllowOut(driver->iptables,
-                                          network->def->network,
-                                          network->def->bridge,
-                                          network->def->forwardDev))) {
-        virReportSystemError(conn, err,
-                             _("failed to add iptables rule to allow forwarding from '%s'"),
-                             network->def->bridge);
-        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))) {
-        virReportSystemError(conn, err,
-                             _("failed to add iptables rule to allow forwarding to '%s'"),
-                             network->def->bridge);
-        goto masqerr2;
-    }
-
-    /* enable masquerading */
-    if ((err = iptablesAddForwardMasquerade(driver->iptables,
-                                            network->def->network,
-                                            network->def->forwardDev))) {
-        virReportSystemError(conn, err,
-                             _("failed to add iptables rule to enable masquerading to '%s'\n"),
-                             network->def->forwardDev ? network->def->forwardDev : NULL);
-        goto masqerr3;
-    }
-
-    return 1;
-
- 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
-networkAddRoutingIptablesRules(virConnectPtr conn,
-                      struct network_driver *driver,
-                      virNetworkObjPtr network) {
-    int err;
-    /* allow routing packets from the bridge interface */
-    if ((err = iptablesAddForwardAllowOut(driver->iptables,
-                                          network->def->network,
-                                          network->def->bridge,
-                                          network->def->forwardDev))) {
-        virReportSystemError(conn, err,
-                             _("failed to add iptables rule to allow routing from '%s'"),
-                             network->def->bridge);
-        goto routeerr1;
-    }
-
-    /* allow routing packets to the bridge interface */
-    if ((err = iptablesAddForwardAllowIn(driver->iptables,
-                                         network->def->network,
-                                         network->def->bridge,
-                                         network->def->forwardDev))) {
-        virReportSystemError(conn, err,
-                             _("failed to add iptables rule to allow routing to '%s'"),
-                             network->def->bridge);
-        goto routeerr2;
-    }
-
-    return 1;
-
-
- routeerr2:
-    iptablesRemoveForwardAllowOut(driver->iptables,
-                                  network->def->network,
-                                  network->def->bridge,
-                                  network->def->forwardDev);
- routeerr1:
-    return 0;
-}
-
-static int
-networkAddIptablesRules(virConnectPtr conn,
-                      struct network_driver *driver,
-                      virNetworkObjPtr network) {
-    int err;
-
-    /* allow DHCP requests through to dnsmasq */
-    if ((err = iptablesAddTcpInput(driver->iptables, network->def->bridge, 67))) {
-        virReportSystemError(conn, err,
-                             _("failed to add iptables rule to allow DHCP requests from '%s'"),
-                             network->def->bridge);
-        goto err1;
-    }
-
-    if ((err = iptablesAddUdpInput(driver->iptables, network->def->bridge, 67))) {
-        virReportSystemError(conn, err,
-                             _("failed to add iptables rule to allow DHCP requests from '%s'"),
-                             network->def->bridge);
-        goto err2;
-    }
-
-    /* allow DNS requests through to dnsmasq */
-    if ((err = iptablesAddTcpInput(driver->iptables, network->def->bridge, 53))) {
-        virReportSystemError(conn, err,
-                             _("failed to add iptables rule to allow DNS requests from '%s'"),
-                             network->def->bridge);
-        goto err3;
-    }
-
-    if ((err = iptablesAddUdpInput(driver->iptables, network->def->bridge, 53))) {
-        virReportSystemError(conn, err,
-                             _("failed to add iptables rule to allow DNS requests from '%s'"),
-                             network->def->bridge);
-        goto err4;
-    }
-
-
-    /* Catch all rules to block forwarding to/from bridges */
-
-    if ((err = iptablesAddForwardRejectOut(driver->iptables, network->def->bridge))) {
-        virReportSystemError(conn, err,
-                             _("failed to add iptables rule to block outbound traffic from '%s'"),
-                             network->def->bridge);
-        goto err5;
-    }
-
-    if ((err = iptablesAddForwardRejectIn(driver->iptables, network->def->bridge))) {
-        virReportSystemError(conn, err,
-                             _("failed to add iptables rule to block inbound traffic to '%s'"),
-                             network->def->bridge);
-        goto err6;
-    }
-
-    /* Allow traffic between guests on the same bridge */
-    if ((err = iptablesAddForwardAllowCross(driver->iptables, network->def->bridge))) {
-        virReportSystemError(conn, err,
-                             _("failed to add iptables rule to allow cross bridge traffic on '%s'"),
-                             network->def->bridge);
-        goto err7;
-    }
-
-
-    /* If masquerading is enabled, set up the rules*/
-    if (network->def->forwardType == VIR_NETWORK_FORWARD_NAT &&
-        !networkAddMasqueradingIptablesRules(conn, driver, network))
-        goto err8;
-    /* else if routing is enabled, set up the rules*/
-    else if (network->def->forwardType == VIR_NETWORK_FORWARD_ROUTE &&
-             !networkAddRoutingIptablesRules(conn, driver, network))
-        goto err8;
-
-    iptablesSaveRules(driver->iptables);
-
-    return 1;
-
- err8:
-    iptablesRemoveForwardAllowCross(driver->iptables,
-                                    network->def->bridge);
- err7:
-    iptablesRemoveForwardRejectIn(driver->iptables,
-                                  network->def->bridge);
- err6:
-    iptablesRemoveForwardRejectOut(driver->iptables,
-                                   network->def->bridge);
- err5:
-    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) {
-    if (network->def->forwardType != VIR_NETWORK_FORWARD_NONE) {
-        iptablesRemoveForwardMasquerade(driver->iptables,
-                                        network->def->network,
-                                        network->def->forwardDev);
-
-        if (network->def->forwardType == VIR_NETWORK_FORWARD_NAT)
-            iptablesRemoveForwardAllowRelatedIn(driver->iptables,
-                                                network->def->network,
-                                                network->def->bridge,
-                                                network->def->forwardDev);
-        else if (network->def->forwardType == VIR_NETWORK_FORWARD_ROUTE)
-            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);
-    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);
-    iptablesSaveRules(driver->iptables);
-}
-
-/* Enable IP Forwarding. Return 0 for success, -1 for failure. */
-static int
-networkEnableIpForwarding(void)
-{
-    return virFileWriteStr("/proc/sys/net/ipv4/ip_forward", "1\n");
-}
-
-#define SYSCTL_PATH "/proc/sys"
-
-static int networkDisableIPV6(virConnectPtr conn,
-                              virNetworkObjPtr network)
-{
-    char *field = NULL;
-    int ret = -1;
-
-    if (virAsprintf(&field, SYSCTL_PATH "/net/ipv6/conf/%s/disable_ipv6", network->def->bridge) < 0) {
-        virReportOOMError(conn);
-        goto cleanup;
-    }
-
-    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;
-    }
-
-    if (virFileWriteStr(field, "1") < 0) {
-        virReportSystemError(conn, errno,
-                             _("cannot enable %s"), field);
-        goto cleanup;
-    }
-    VIR_FREE(field);
-
-    if (virAsprintf(&field, SYSCTL_PATH "/net/ipv6/conf/%s/accept_ra", network->def->bridge) < 0) {
-        virReportOOMError(conn);
-        goto cleanup;
-    }
-
-    if (virFileWriteStr(field, "0") < 0) {
-        virReportSystemError(conn, errno,
-                             _("cannot disable %s"), field);
-        goto cleanup;
-    }
-    VIR_FREE(field);
-
-    if (virAsprintf(&field, SYSCTL_PATH "/net/ipv6/conf/%s/autoconf", network->def->bridge) < 0) {
-        virReportOOMError(conn);
-        goto cleanup;
-    }
-
-    if (virFileWriteStr(field, "1") < 0) {
-        virReportSystemError(conn, errno,
-                             _("cannot enable %s"), field);
-        goto cleanup;
-    }
-
-    ret = 0;
-cleanup:
-    VIR_FREE(field);
-    return ret;
-}
-
-static int networkStartNetworkDaemon(virConnectPtr conn,
-                                   struct network_driver *driver,
-                                   virNetworkObjPtr network) {
-    int err;
-
-    if (virNetworkIsActive(network)) {
-        networkReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
-                         "%s", _("network is already active"));
-        return -1;
-    }
-
-    if ((err = brAddBridge(driver->brctl, network->def->bridge))) {
-        virReportSystemError(conn, err,
-                             _("cannot create bridge '%s'"),
-                             network->def->bridge);
-        return -1;
-    }
-
-    if (networkDisableIPV6(conn, network) < 0)
-        goto err_delbr;
-
-    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))) {
-        virReportSystemError(conn, err,
-                             _("cannot set IP address on bridge '%s' to '%s'"),
-                             network->def->bridge, network->def->ipAddress);
-        goto err_delbr;
-    }
-
-    if (network->def->netmask &&
-        (err = brSetInetNetmask(driver->brctl, network->def->bridge, network->def->netmask))) {
-        virReportSystemError(conn, err,
-                             _("cannot set netmask on bridge '%s' to '%s'"),
-                             network->def->bridge, network->def->netmask);
-        goto err_delbr;
-    }
-
-    if ((err = brSetInterfaceUp(driver->brctl, network->def->bridge, 1))) {
-        virReportSystemError(conn, err,
-                             _("failed to bring the bridge '%s' up"),
-                             network->def->bridge);
-        goto err_delbr;
-    }
-
-    if (!networkAddIptablesRules(conn, driver, network))
-        goto err_delbr1;
-
-    if (network->def->forwardType != VIR_NETWORK_FORWARD_NONE &&
-        networkEnableIpForwarding() < 0) {
-        virReportSystemError(conn, errno, "%s",
-                             _("failed to enable IP forwarding"));
-        goto err_delbr2;
-    }
-
-    if ((network->def->ipAddress ||
-         network->def->nranges) &&
-        dhcpStartDhcpDaemon(conn, network) < 0)
-        goto err_delbr2;
-
-
-    /* Persist the live configuration now we have bridge info  */
-    if (virNetworkSaveConfig(conn, NETWORK_STATE_DIR, network->def) < 0) {
-        goto err_kill;
-    }
-
-    network->active = 1;
-
-    return 0;
-
- err_kill:
-    if (network->dnsmasqPid > 0) {
-        kill(network->dnsmasqPid, SIGTERM);
-        network->dnsmasqPid = -1;
-    }
-
- err_delbr2:
-    networkRemoveIptablesRules(driver, network);
-
- err_delbr1:
-    if ((err = brSetInterfaceUp(driver->brctl, network->def->bridge, 0))) {
-        char ebuf[1024];
-        VIR_WARN(_("Failed to bring down bridge '%s' : %s\n"),
-                 network->def->bridge, virStrerror(err, ebuf, sizeof ebuf));
-    }
-
- err_delbr:
-    if ((err = brDeleteBridge(driver->brctl, network->def->bridge))) {
-        char ebuf[1024];
-        VIR_WARN(_("Failed to delete bridge '%s' : %s\n"),
-                 network->def->bridge, virStrerror(err, ebuf, sizeof ebuf));
-    }
-
-    return -1;
-}
-
-
-static int networkShutdownNetworkDaemon(virConnectPtr conn,
-                                        struct network_driver *driver,
-                                        virNetworkObjPtr network) {
-    int err;
-    char *stateFile;
-
-    VIR_INFO(_("Shutting down network '%s'\n"), network->def->name);
-
-    if (!virNetworkIsActive(network))
-        return 0;
-
-    stateFile = virNetworkConfigFile(conn, NETWORK_STATE_DIR, network->def->name);
-    if (!stateFile)
-        return -1;
-
-    unlink(stateFile);
-    VIR_FREE(stateFile);
-
-    if (network->dnsmasqPid > 0)
-        kill(network->dnsmasqPid, SIGTERM);
-
-    networkRemoveIptablesRules(driver, network);
-
-    char ebuf[1024];
-    if ((err = brSetInterfaceUp(driver->brctl, network->def->bridge, 0))) {
-        VIR_WARN(_("Failed to bring down bridge '%s' : %s\n"),
-                 network->def->bridge, virStrerror(err, ebuf, sizeof ebuf));
-    }
-
-    if ((err = brDeleteBridge(driver->brctl, network->def->bridge))) {
-        VIR_WARN(_("Failed to delete bridge '%s' : %s\n"),
-                 network->def->bridge, virStrerror(err, ebuf, sizeof ebuf));
-    }
-
-    /* See if its still alive and really really kill it */
-    if (network->dnsmasqPid > 0 &&
-        (kill(network->dnsmasqPid, 0) == 0))
-        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;
-}
-
-
-static virNetworkPtr networkLookupByUUID(virConnectPtr conn,
-                                         const unsigned char *uuid) {
-    struct network_driver *driver = conn->networkPrivateData;
-    virNetworkObjPtr network;
-    virNetworkPtr ret = NULL;
-
-    networkDriverLock(driver);
-    network = virNetworkFindByUUID(&driver->networks, uuid);
-    networkDriverUnlock(driver);
-    if (!network) {
-        networkReportError(conn, NULL, NULL, VIR_ERR_NO_NETWORK,
-                         "%s", _("no network with matching uuid"));
-        goto cleanup;
-    }
-
-    ret = virGetNetwork(conn, network->def->name, network->def->uuid);
-
-cleanup:
-    if (network)
-        virNetworkObjUnlock(network);
-    return ret;
-}
-
-static virNetworkPtr networkLookupByName(virConnectPtr conn,
-                                         const char *name) {
-    struct network_driver *driver = conn->networkPrivateData;
-    virNetworkObjPtr network;
-    virNetworkPtr ret = NULL;
-
-    networkDriverLock(driver);
-    network = virNetworkFindByName(&driver->networks, name);
-    networkDriverUnlock(driver);
-    if (!network) {
-        networkReportError(conn, NULL, NULL, VIR_ERR_NO_NETWORK,
-                         _("no network with matching name '%s'"), name);
-        goto cleanup;
-    }
-
-    ret = virGetNetwork(conn, network->def->name, network->def->uuid);
-
-cleanup:
-    if (network)
-        virNetworkObjUnlock(network);
-    return ret;
-}
-
-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) {
-    int nactive = 0, i;
-    struct network_driver *driver = conn->networkPrivateData;
-
-    networkDriverLock(driver);
-    for (i = 0 ; i < driver->networks.count ; i++) {
-        virNetworkObjLock(driver->networks.objs[i]);
-        if (virNetworkIsActive(driver->networks.objs[i]))
-            nactive++;
-        virNetworkObjUnlock(driver->networks.objs[i]);
-    }
-    networkDriverUnlock(driver);
-
-    return nactive;
-}
-
-static int networkListNetworks(virConnectPtr conn, char **const names, int nnames) {
-    struct network_driver *driver = conn->networkPrivateData;
-    int got = 0, i;
-
-    networkDriverLock(driver);
-    for (i = 0 ; i < driver->networks.count && got < nnames ; i++) {
-        virNetworkObjLock(driver->networks.objs[i]);
-        if (virNetworkIsActive(driver->networks.objs[i])) {
-            if (!(names[got] = strdup(driver->networks.objs[i]->def->name))) {
-                virNetworkObjUnlock(driver->networks.objs[i]);
-                virReportOOMError(conn);
-                goto cleanup;
-            }
-            got++;
-        }
-        virNetworkObjUnlock(driver->networks.objs[i]);
-    }
-    networkDriverUnlock(driver);
-
-    return got;
-
- cleanup:
-    networkDriverUnlock(driver);
-    for (i = 0 ; i < got ; i++)
-        VIR_FREE(names[i]);
-    return -1;
-}
-
-static int networkNumDefinedNetworks(virConnectPtr conn) {
-    int ninactive = 0, i;
-    struct network_driver *driver = conn->networkPrivateData;
-
-    networkDriverLock(driver);
-    for (i = 0 ; i < driver->networks.count ; i++) {
-        virNetworkObjLock(driver->networks.objs[i]);
-        if (!virNetworkIsActive(driver->networks.objs[i]))
-            ninactive++;
-        virNetworkObjUnlock(driver->networks.objs[i]);
-    }
-    networkDriverUnlock(driver);
-
-    return ninactive;
-}
-
-static int networkListDefinedNetworks(virConnectPtr conn, char **const names, int nnames) {
-    struct network_driver *driver = conn->networkPrivateData;
-    int got = 0, i;
-
-    networkDriverLock(driver);
-    for (i = 0 ; i < driver->networks.count && got < nnames ; i++) {
-        virNetworkObjLock(driver->networks.objs[i]);
-        if (!virNetworkIsActive(driver->networks.objs[i])) {
-            if (!(names[got] = strdup(driver->networks.objs[i]->def->name))) {
-                virNetworkObjUnlock(driver->networks.objs[i]);
-                virReportOOMError(conn);
-                goto cleanup;
-            }
-            got++;
-        }
-        virNetworkObjUnlock(driver->networks.objs[i]);
-    }
-    networkDriverUnlock(driver);
-    return got;
-
- cleanup:
-    networkDriverUnlock(driver);
-    for (i = 0 ; i < got ; i++)
-        VIR_FREE(names[i]);
-    return -1;
-}
-
-static virNetworkPtr networkCreate(virConnectPtr conn, const char *xml) {
-    struct network_driver *driver = conn->networkPrivateData;
-    virNetworkDefPtr def;
-    virNetworkObjPtr network = NULL;
-    virNetworkPtr ret = NULL;
-
-    networkDriverLock(driver);
-
-    if (!(def = virNetworkDefParseString(conn, xml)))
-        goto cleanup;
-
-    if (virNetworkSetBridgeName(conn, &driver->networks, def, 1))
-        goto cleanup;
-
-    if (!(network = virNetworkAssignDef(conn,
-                                        &driver->networks,
-                                        def)))
-        goto cleanup;
-    def = NULL;
-
-    if (networkStartNetworkDaemon(conn, driver, network) < 0) {
-        virNetworkRemoveInactive(&driver->networks,
-                                 network);
-        network = NULL;
-        goto cleanup;
-    }
-
-    ret = virGetNetwork(conn, network->def->name, network->def->uuid);
-
-cleanup:
-    virNetworkDefFree(def);
-    if (network)
-        virNetworkObjUnlock(network);
-    networkDriverUnlock(driver);
-    return ret;
-}
-
-static virNetworkPtr networkDefine(virConnectPtr conn, const char *xml) {
-    struct network_driver *driver = conn->networkPrivateData;
-    virNetworkDefPtr def;
-    virNetworkObjPtr network = NULL;
-    virNetworkPtr ret = NULL;
-
-    networkDriverLock(driver);
-
-    if (!(def = virNetworkDefParseString(conn, xml)))
-        goto cleanup;
-
-    if (virNetworkSetBridgeName(conn, &driver->networks, def, 1))
-        goto cleanup;
-
-    if (!(network = virNetworkAssignDef(conn,
-                                        &driver->networks,
-                                        def)))
-        goto cleanup;
-    def = NULL;
-
-    network->persistent = 1;
-
-    if (virNetworkSaveConfig(conn,
-                             driver->networkConfigDir,
-                             network->newDef ? network->newDef : network->def) < 0) {
-        virNetworkRemoveInactive(&driver->networks,
-                                 network);
-        network = NULL;
-        goto cleanup;
-    }
-
-    ret = virGetNetwork(conn, network->def->name, network->def->uuid);
-
-cleanup:
-    virNetworkDefFree(def);
-    if (network)
-        virNetworkObjUnlock(network);
-    networkDriverUnlock(driver);
-    return ret;
-}
-
-static int networkUndefine(virNetworkPtr net) {
-    struct network_driver *driver = net->conn->networkPrivateData;
-    virNetworkObjPtr network = NULL;
-    int ret = -1;
-
-    networkDriverLock(driver);
-
-    network = virNetworkFindByUUID(&driver->networks, net->uuid);
-    if (!network) {
-        networkReportError(net->conn, NULL, net, VIR_ERR_INVALID_DOMAIN,
-                           "%s", _("no network with matching uuid"));
-        goto cleanup;
-    }
-
-    if (virNetworkIsActive(network)) {
-        networkReportError(net->conn, NULL, net, VIR_ERR_INTERNAL_ERROR,
-                           "%s", _("network is still active"));
-        goto cleanup;
-    }
-
-    if (virNetworkDeleteConfig(net->conn,
-                               driver->networkConfigDir,
-                               driver->networkAutostartDir,
-                               network) < 0)
-        goto cleanup;
-
-    virNetworkRemoveInactive(&driver->networks,
-                             network);
-    network = NULL;
-    ret = 0;
-
-cleanup:
-    if (network)
-        virNetworkObjUnlock(network);
-    networkDriverUnlock(driver);
-    return ret;
-}
-
-static int networkStart(virNetworkPtr net) {
-    struct network_driver *driver = net->conn->networkPrivateData;
-    virNetworkObjPtr network;
-    int ret = -1;
-
-    networkDriverLock(driver);
-    network = virNetworkFindByUUID(&driver->networks, net->uuid);
-
-    if (!network) {
-        networkReportError(net->conn, NULL, net, VIR_ERR_INVALID_NETWORK,
-                           "%s", _("no network with matching uuid"));
-        goto cleanup;
-    }
-
-    ret = networkStartNetworkDaemon(net->conn, driver, network);
-
-cleanup:
-    if (network)
-        virNetworkObjUnlock(network);
-    networkDriverUnlock(driver);
-    return ret;
-}
-
-static int networkDestroy(virNetworkPtr net) {
-    struct network_driver *driver = net->conn->networkPrivateData;
-    virNetworkObjPtr network;
-    int ret = -1;
-
-    networkDriverLock(driver);
-    network = virNetworkFindByUUID(&driver->networks, net->uuid);
-
-    if (!network) {
-        networkReportError(net->conn, NULL, net, VIR_ERR_INVALID_NETWORK,
-                           "%s", _("no network with matching uuid"));
-        goto cleanup;
-    }
-
-    if (!virNetworkIsActive(network)) {
-        networkReportError(net->conn, NULL, net, VIR_ERR_INTERNAL_ERROR,
-                           "%s", _("network is not active"));
-        goto cleanup;
-    }
-
-    ret = networkShutdownNetworkDaemon(net->conn, driver, network);
-    if (!network->persistent) {
-        virNetworkRemoveInactive(&driver->networks,
-                                 network);
-        network = NULL;
-    }
-
-cleanup:
-    if (network)
-        virNetworkObjUnlock(network);
-    networkDriverUnlock(driver);
-    return ret;
-}
-
-static char *networkDumpXML(virNetworkPtr net, int flags ATTRIBUTE_UNUSED) {
-    struct network_driver *driver = net->conn->networkPrivateData;
-    virNetworkObjPtr network;
-    char *ret = NULL;
-
-    networkDriverLock(driver);
-    network = virNetworkFindByUUID(&driver->networks, net->uuid);
-    networkDriverUnlock(driver);
-
-    if (!network) {
-        networkReportError(net->conn, NULL, net, VIR_ERR_INVALID_NETWORK,
-                           "%s", _("no network with matching uuid"));
-        goto cleanup;
-    }
-
-    ret = virNetworkDefFormat(net->conn, network->def);
-
-cleanup:
-    if (network)
-        virNetworkObjUnlock(network);
-    return ret;
-}
-
-static char *networkGetBridgeName(virNetworkPtr net) {
-    struct network_driver *driver = net->conn->networkPrivateData;
-    virNetworkObjPtr network;
-    char *bridge = NULL;
-
-    networkDriverLock(driver);
-    network = virNetworkFindByUUID(&driver->networks, net->uuid);
-    networkDriverUnlock(driver);
-
-    if (!network) {
-        networkReportError(net->conn, NULL, net, VIR_ERR_INVALID_NETWORK,
-                           "%s", _("no network with matching id"));
-        goto cleanup;
-    }
-
-    if (!(network->def->bridge)) {
-        networkReportError(net->conn, NULL, net, VIR_ERR_INTERNAL_ERROR,
-                           _("network '%s' does not have a bridge name."),
-                           network->def->name);
-        goto cleanup;
-    }
-
-    bridge = strdup(network->def->bridge);
-    if (!bridge)
-        virReportOOMError(net->conn);
-
-cleanup:
-    if (network)
-        virNetworkObjUnlock(network);
-    return bridge;
-}
-
-static int networkGetAutostart(virNetworkPtr net,
-                             int *autostart) {
-    struct network_driver *driver = net->conn->networkPrivateData;
-    virNetworkObjPtr network;
-    int ret = -1;
-
-    networkDriverLock(driver);
-    network = virNetworkFindByUUID(&driver->networks, net->uuid);
-    networkDriverUnlock(driver);
-    if (!network) {
-        networkReportError(net->conn, NULL, net, VIR_ERR_INVALID_NETWORK,
-                         "%s", _("no network with matching uuid"));
-        goto cleanup;
-    }
-
-    *autostart = network->autostart;
-    ret = 0;
-
-cleanup:
-    if (network)
-        virNetworkObjUnlock(network);
-    return ret;
-}
-
-static int networkSetAutostart(virNetworkPtr net,
-                               int autostart) {
-    struct network_driver *driver = net->conn->networkPrivateData;
-    virNetworkObjPtr network;
-    char *configFile = NULL, *autostartLink = NULL;
-    int ret = -1;
-
-    networkDriverLock(driver);
-    network = virNetworkFindByUUID(&driver->networks, net->uuid);
-
-    if (!network) {
-        networkReportError(net->conn, NULL, net, VIR_ERR_INVALID_NETWORK,
-                         "%s", _("no network with matching uuid"));
-        goto cleanup;
-    }
-
-    if (!network->persistent) {
-        networkReportError(net->conn, NULL, net, VIR_ERR_INTERNAL_ERROR,
-                         "%s", _("cannot set autostart for transient network"));
-        goto cleanup;
-    }
-
-    autostart = (autostart != 0);
-
-    if (network->autostart != autostart) {
-        if ((configFile = virNetworkConfigFile(net->conn, driver->networkConfigDir, network->def->name)) == NULL)
-            goto cleanup;
-        if ((autostartLink = virNetworkConfigFile(net->conn, driver->networkAutostartDir, network->def->name)) == NULL)
-            goto cleanup;
-
-        if (autostart) {
-            if (virFileMakePath(driver->networkAutostartDir)) {
-                virReportSystemError(net->conn, errno,
-                                     _("cannot create autostart directory '%s'"),
-                                     driver->networkAutostartDir);
-                goto cleanup;
-            }
-
-            if (symlink(configFile, autostartLink) < 0) {
-                virReportSystemError(net->conn, errno,
-                                     _("Failed to create symlink '%s' to '%s'"),
-                                     autostartLink, configFile);
-                goto cleanup;
-            }
-        } else {
-            if (unlink(autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) {
-                virReportSystemError(net->conn, errno,
-                                     _("Failed to delete symlink '%s'"),
-                                     autostartLink);
-                goto cleanup;
-            }
-        }
-
-        network->autostart = autostart;
-    }
-    ret = 0;
-
-cleanup:
-    VIR_FREE(configFile);
-    VIR_FREE(autostartLink);
-    if (network)
-        virNetworkObjUnlock(network);
-    networkDriverUnlock(driver);
-    return ret;
-}
-
-
-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 */
-};
-
-static virStateDriver networkStateDriver = {
-    networkStartup,
-    networkShutdown,
-    networkReload,
-    networkActive,
-};
-
-int networkRegister(void) {
-    virRegisterNetworkDriver(&networkDriver);
-    virRegisterStateDriver(&networkStateDriver);
-    return 0;
-}
diff --git a/src/network_driver.h b/src/network_driver.h
deleted file mode 100644 (file)
index 5951833..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * network_driver.h: core driver methods for managing networks
- *
- * Copyright (C) 2006, 2007 Red Hat, Inc.
- * 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>
- */
-
-
-#ifndef __VIR_NETWORK__DRIVER_H
-#define __VIR_NETWORK__DRIVER_H
-
-#include <config.h>
-
-#include "internal.h"
-
-int networkRegister(void);
-
-#endif /* __VIR_NETWORK__DRIVER_H */