~serge-hallyn/ubuntu/raring/libvirt/libvirt-hugepages

« back to all changes in this revision

Viewing changes to .pc/Don-t-pass-empty-arguments-to-dnsmasq.patch/src/network/bridge_driver.c

  • Committer: Package Import Robot
  • Author(s): Serge Hallyn
  • Date: 2011-05-11 12:29:51 UTC
  • mfrom: (1.4.1) (3.4.30 sid)
  • mto: This revision was merged to the branch mainline in revision 167.
  • Revision ID: package-import@ubuntu.com-20110511122951-ku5fk1tv37o5aymm
Tags: 0.9.1-1ubuntu1
* Resynchronize and merge from Debian unstable (LP: #794378). Remaining
  changes:
  - debian/control:
    * set X-Python-Version to 2.7, as 2.6 is not in oneiric.
    * set ubuntu maintainer
    * Build-Depends:
      - remove [linux-any] from all dependencies
      - remove [!linux-any] deps
      - swap libxen to libxen3, qemu to qemu-kvm, and open-iscsi to
        open-iscsi-utils in Build-Depends
      - remove virtualbox-ose Build-Depends
      - add parted and libapparmor-dev Build-Depends
    * convert Vcs-Git to Xs-Debian-Vcs-Git
    * libvirt-bin Depends: move netcat-openbsd, bridge-utils, dnsmasq-base
      (>= 2.46-1), and iptables from Recommends to Depends
    * libvirt-bin Recommends: move qemu to Suggests
    * libvirt-bin Suggests: add apparmor
    * libvirt0 Recommands: move lvm2 to Suggests
  - keep debian/libvirt-bin.apport
  - keep debian/libvirt-bin.cron.daily
  - debian/libvirt-bin.dirs:
    * add apparmor, cron.daily, and apport dirs
  - debian/libvirt-bin.examples:
    * add debian/libvirt-suspendonreboot
  - debian/libvirt-bin.install:
    * add /etc/apparmor.d files
    * add apport hook
  - debian/libvirt-bin.manpages:
    * add debian/libvirt-migrate-qemu-disks.1
  - debian/libvirt-bin.postinst:
    * replace libvirt groupname with libvirtd
    * add each admin user to libvirtd group
    * call apparmor_parser on usr.sbin.libvirtd and
      usr.lib.libvirt.virt-aa-helper
    * call 'libvirt-migrate-qemu-disks -a' after
      libvirt-bin has started if migrating from
      older than 0.8.3-1ubuntu1
  - debian/libvirt-bin.postrm:
    * replace libvirt groupname with libvirtd
    * remove usr.sbin.libvirtd and
      usr.lib.libvirt.virt-aa-helper
  - keep added files under debian/:
    * libvirt-bin.upstart
    * libvirt-migrate-qemu-disks
    * libvirt-migrate-qemu-disks.1
    * libvirt-suspendonreboot
    * apparmor profiles
  - debian/README.Debian:
    * add 'Apparmor Profile' section
    * add 'Disk migration' section
  - debian/rules:
    * move include of debhelper.mk to top of file so DEB_HOST_ARCH_OS
      is defined.
    * don't build with vbox since virtualbox-ose is in universe
      - remove WITH_VBOX, add explicit --without-vbox
    * add --with-apparmor to DEB_CONFIGURE_EXTRA_FLAGS
    * set DEB_DH_INSTALLINIT_ARGS to '--upstart-only'
    * remove unneeded binary-install/libvirt-bin:: and clean::
      sections (they only deal with sysvinit stuff)
    * add build/libvirt-bin:: section to install
      - apparmor files
      - apport hooks
      - libvirt-migrate-qemu-disks
* debian/patches/series:
  - don't apply Disable-CHECKSUM-rule.patch: our iptables can do this
  - don't apply Debian-specific Debianize-libvirt-guests.patch (sysvinit only)
  - don't apply Disable qemu-disable-network.diff.patch
* debian/patches:
  - drop 9007-fix-daemon-conf-ftbfs.patch (looks like it may be fixed)
  - drop patches applied upstream:
    * 9022-drop-booton-when-kernel-specified.patch
    * 9023-fix-lxc-console-hangup.patch
    * 9024-fix-broken-commandtest.patch
    * 9025-Pass-virSecurityManagerPtr-to-virSecurityDAC-Set-Res.patch
    * 9026-security-avoid-memory-leak.patch
    * 9027-CVE-2011-1146.patch
  - keep patches:
    * 9000-delayed_iff_up_bridge.patch
    * 9001-dont_clobber_existing_bridges.patch
    * 9002-better_default_uri_virsh.patch
    * 9003-better-default-arch.patch
    * 9004-libvirtd-group-name.patch
    * 9005-increase-unix-socket-timeout.patch
    * 9006-default-config-test-case.patch
    * 9011-move-ebtables-script.patch (refreshed)
    * 9014-skip-nodeinfotest.patch (modified to make it apply)
    * 9020-lp545795.patch (modified to make it still apply)
    * 9021-fix-uint64_t.patch
    * 9022-allows-lxc-containers-with-lxcguest.patch (renamed, modified
      to make it still apply, and added DEP-3 tags).
  - new patches:
    * 9023-disable-test-poll.patch - don't run broken test-poll

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * bridge_driver.c: core driver methods for managing network
3
 
 *
4
 
 * Copyright (C) 2006-2011 Red Hat, Inc.
5
 
 * Copyright (C) 2006 Daniel P. Berrange
6
 
 *
7
 
 * This library is free software; you can redistribute it and/or
8
 
 * modify it under the terms of the GNU Lesser General Public
9
 
 * License as published by the Free Software Foundation; either
10
 
 * version 2.1 of the License, or (at your option) any later version.
11
 
 *
12
 
 * This library is distributed in the hope that it will be useful,
13
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 
 * Lesser General Public License for more details.
16
 
 *
17
 
 * You should have received a copy of the GNU Lesser General Public
18
 
 * License along with this library; if not, write to the Free Software
19
 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
20
 
 *
21
 
 * Author: Daniel P. Berrange <berrange@redhat.com>
22
 
 */
23
 
 
24
 
#include <config.h>
25
 
 
26
 
#include <sys/types.h>
27
 
#include <sys/poll.h>
28
 
#include <dirent.h>
29
 
#include <limits.h>
30
 
#include <string.h>
31
 
#include <stdio.h>
32
 
#include <stdarg.h>
33
 
#include <stdlib.h>
34
 
#include <unistd.h>
35
 
#include <errno.h>
36
 
#include <sys/utsname.h>
37
 
#include <sys/stat.h>
38
 
#include <fcntl.h>
39
 
#include <signal.h>
40
 
#include <paths.h>
41
 
#include <pwd.h>
42
 
#include <stdio.h>
43
 
#include <sys/wait.h>
44
 
#include <sys/ioctl.h>
45
 
 
46
 
#include "virterror_internal.h"
47
 
#include "datatypes.h"
48
 
#include "bridge_driver.h"
49
 
#include "network_conf.h"
50
 
#include "driver.h"
51
 
#include "event.h"
52
 
#include "buf.h"
53
 
#include "util.h"
54
 
#include "command.h"
55
 
#include "memory.h"
56
 
#include "uuid.h"
57
 
#include "iptables.h"
58
 
#include "bridge.h"
59
 
#include "logging.h"
60
 
#include "dnsmasq.h"
61
 
#include "util/network.h"
62
 
#include "configmake.h"
63
 
 
64
 
#define NETWORK_PID_DIR LOCALSTATEDIR "/run/libvirt/network"
65
 
#define NETWORK_STATE_DIR LOCALSTATEDIR "/lib/libvirt/network"
66
 
 
67
 
#define DNSMASQ_STATE_DIR LOCALSTATEDIR "/lib/libvirt/dnsmasq"
68
 
#define RADVD_STATE_DIR LOCALSTATEDIR "/lib/libvirt/radvd"
69
 
 
70
 
#define VIR_FROM_THIS VIR_FROM_NETWORK
71
 
 
72
 
#define networkReportError(code, ...)                                   \
73
 
    virReportErrorHelper(NULL, VIR_FROM_NETWORK, code, __FILE__,        \
74
 
                         __FUNCTION__, __LINE__, __VA_ARGS__)
75
 
 
76
 
/* Main driver state */
77
 
struct network_driver {
78
 
    virMutex lock;
79
 
 
80
 
    virNetworkObjList networks;
81
 
 
82
 
    iptablesContext *iptables;
83
 
    brControl *brctl;
84
 
    char *networkConfigDir;
85
 
    char *networkAutostartDir;
86
 
    char *logDir;
87
 
};
88
 
 
89
 
 
90
 
static void networkDriverLock(struct network_driver *driver)
91
 
{
92
 
    virMutexLock(&driver->lock);
93
 
}
94
 
static void networkDriverUnlock(struct network_driver *driver)
95
 
{
96
 
    virMutexUnlock(&driver->lock);
97
 
}
98
 
 
99
 
static int networkShutdown(void);
100
 
 
101
 
static int networkStartNetworkDaemon(struct network_driver *driver,
102
 
                                     virNetworkObjPtr network);
103
 
 
104
 
static int networkShutdownNetworkDaemon(struct network_driver *driver,
105
 
                                        virNetworkObjPtr network);
106
 
 
107
 
static void networkReloadIptablesRules(struct network_driver *driver);
108
 
 
109
 
static struct network_driver *driverState = NULL;
110
 
 
111
 
static char *
112
 
networkRadvdPidfileBasename(const char *netname)
113
 
{
114
 
    /* this is simple but we want to be sure it's consistently done */
115
 
    char *pidfilebase;
116
 
 
117
 
    virAsprintf(&pidfilebase, "%s-radvd", netname);
118
 
    return pidfilebase;
119
 
}
120
 
 
121
 
static char *
122
 
networkRadvdConfigFileName(const char *netname)
123
 
{
124
 
    char *configfile;
125
 
 
126
 
    virAsprintf(&configfile, RADVD_STATE_DIR "/%s-radvd.conf",
127
 
                netname);
128
 
    return configfile;
129
 
}
130
 
 
131
 
static void
132
 
networkFindActiveConfigs(struct network_driver *driver) {
133
 
    unsigned int i;
134
 
 
135
 
    for (i = 0 ; i < driver->networks.count ; i++) {
136
 
        virNetworkObjPtr obj = driver->networks.objs[i];
137
 
        virNetworkDefPtr tmp;
138
 
        char *config;
139
 
 
140
 
        virNetworkObjLock(obj);
141
 
 
142
 
        if ((config = virNetworkConfigFile(NETWORK_STATE_DIR,
143
 
                                           obj->def->name)) == NULL) {
144
 
            virNetworkObjUnlock(obj);
145
 
            continue;
146
 
        }
147
 
 
148
 
        if (access(config, R_OK) < 0) {
149
 
            VIR_FREE(config);
150
 
            virNetworkObjUnlock(obj);
151
 
            continue;
152
 
        }
153
 
 
154
 
        /* Try and load the live config */
155
 
        tmp = virNetworkDefParseFile(config);
156
 
        VIR_FREE(config);
157
 
        if (tmp) {
158
 
            obj->newDef = obj->def;
159
 
            obj->def = tmp;
160
 
        }
161
 
 
162
 
        /* If bridge exists, then mark it active */
163
 
        if (obj->def->bridge &&
164
 
            brHasBridge(driver->brctl, obj->def->bridge) == 0) {
165
 
            obj->active = 1;
166
 
 
167
 
            /* Try and read dnsmasq/radvd pids if any */
168
 
            if (obj->def->ips && (obj->def->nips > 0)) {
169
 
                char *pidpath, *radvdpidbase;
170
 
 
171
 
                if (virFileReadPid(NETWORK_PID_DIR, obj->def->name,
172
 
                                   &obj->dnsmasqPid) == 0) {
173
 
                    /* Check that it's still alive */
174
 
                    if (kill(obj->dnsmasqPid, 0) != 0)
175
 
                        obj->dnsmasqPid = -1;
176
 
                    if (virAsprintf(&pidpath, "/proc/%d/exe", obj->dnsmasqPid) < 0) {
177
 
                        virReportOOMError();
178
 
                        goto cleanup;
179
 
                    }
180
 
                    if (virFileLinkPointsTo(pidpath, DNSMASQ) == 0)
181
 
                        obj->dnsmasqPid = -1;
182
 
                    VIR_FREE(pidpath);
183
 
                }
184
 
 
185
 
                if (!(radvdpidbase = networkRadvdPidfileBasename(obj->def->name))) {
186
 
                    virReportOOMError();
187
 
                    goto cleanup;
188
 
                }
189
 
                if (virFileReadPid(NETWORK_PID_DIR, radvdpidbase,
190
 
                                   &obj->radvdPid) == 0) {
191
 
                    /* Check that it's still alive */
192
 
                    if (kill(obj->radvdPid, 0) != 0)
193
 
                        obj->radvdPid = -1;
194
 
                    if (virAsprintf(&pidpath, "/proc/%d/exe", obj->radvdPid) < 0) {
195
 
                        virReportOOMError();
196
 
                        VIR_FREE(radvdpidbase);
197
 
                        goto cleanup;
198
 
                    }
199
 
                    if (virFileLinkPointsTo(pidpath, RADVD) == 0)
200
 
                        obj->radvdPid = -1;
201
 
                    VIR_FREE(pidpath);
202
 
                }
203
 
                VIR_FREE(radvdpidbase);
204
 
            }
205
 
        }
206
 
 
207
 
    cleanup:
208
 
        virNetworkObjUnlock(obj);
209
 
    }
210
 
}
211
 
 
212
 
 
213
 
static void
214
 
networkAutostartConfigs(struct network_driver *driver) {
215
 
    unsigned int i;
216
 
 
217
 
    for (i = 0 ; i < driver->networks.count ; i++) {
218
 
        virNetworkObjLock(driver->networks.objs[i]);
219
 
        if (driver->networks.objs[i]->autostart &&
220
 
            !virNetworkObjIsActive(driver->networks.objs[i]) &&
221
 
            networkStartNetworkDaemon(driver, driver->networks.objs[i]) < 0) {
222
 
            /* failed to start but already logged */
223
 
        }
224
 
        virNetworkObjUnlock(driver->networks.objs[i]);
225
 
    }
226
 
}
227
 
 
228
 
/**
229
 
 * networkStartup:
230
 
 *
231
 
 * Initialization function for the QEmu daemon
232
 
 */
233
 
static int
234
 
networkStartup(int privileged) {
235
 
    uid_t uid = geteuid();
236
 
    char *base = NULL;
237
 
    int err;
238
 
 
239
 
    if (VIR_ALLOC(driverState) < 0)
240
 
        goto error;
241
 
 
242
 
    if (virMutexInit(&driverState->lock) < 0) {
243
 
        VIR_FREE(driverState);
244
 
        goto error;
245
 
    }
246
 
    networkDriverLock(driverState);
247
 
 
248
 
    if (privileged) {
249
 
        if (virAsprintf(&driverState->logDir,
250
 
                        "%s/log/libvirt/qemu", LOCALSTATEDIR) == -1)
251
 
            goto out_of_memory;
252
 
 
253
 
        if ((base = strdup (SYSCONFDIR "/libvirt")) == NULL)
254
 
            goto out_of_memory;
255
 
    } else {
256
 
        char *userdir = virGetUserDirectory(uid);
257
 
 
258
 
        if (!userdir)
259
 
            goto error;
260
 
 
261
 
        if (virAsprintf(&driverState->logDir,
262
 
                        "%s/.libvirt/qemu/log", userdir) == -1) {
263
 
            VIR_FREE(userdir);
264
 
            goto out_of_memory;
265
 
        }
266
 
 
267
 
        if (virAsprintf(&base, "%s/.libvirt", userdir) == -1) {
268
 
            VIR_FREE(userdir);
269
 
            goto out_of_memory;
270
 
        }
271
 
        VIR_FREE(userdir);
272
 
    }
273
 
 
274
 
    /* Configuration paths are either ~/.libvirt/qemu/... (session) or
275
 
     * /etc/libvirt/qemu/... (system).
276
 
     */
277
 
    if (virAsprintf(&driverState->networkConfigDir, "%s/qemu/networks", base) == -1)
278
 
        goto out_of_memory;
279
 
 
280
 
    if (virAsprintf(&driverState->networkAutostartDir, "%s/qemu/networks/autostart",
281
 
                    base) == -1)
282
 
        goto out_of_memory;
283
 
 
284
 
    VIR_FREE(base);
285
 
 
286
 
    if ((err = brInit(&driverState->brctl))) {
287
 
        virReportSystemError(err, "%s",
288
 
                             _("cannot initialize bridge support"));
289
 
        goto error;
290
 
    }
291
 
 
292
 
    if (!(driverState->iptables = iptablesContextNew())) {
293
 
        goto out_of_memory;
294
 
    }
295
 
 
296
 
 
297
 
    if (virNetworkLoadAllConfigs(&driverState->networks,
298
 
                                 driverState->networkConfigDir,
299
 
                                 driverState->networkAutostartDir) < 0)
300
 
        goto error;
301
 
 
302
 
    networkFindActiveConfigs(driverState);
303
 
    networkReloadIptablesRules(driverState);
304
 
    networkAutostartConfigs(driverState);
305
 
 
306
 
    networkDriverUnlock(driverState);
307
 
 
308
 
    return 0;
309
 
 
310
 
out_of_memory:
311
 
    virReportOOMError();
312
 
 
313
 
error:
314
 
    if (driverState)
315
 
        networkDriverUnlock(driverState);
316
 
 
317
 
    VIR_FREE(base);
318
 
    networkShutdown();
319
 
    return -1;
320
 
}
321
 
 
322
 
/**
323
 
 * networkReload:
324
 
 *
325
 
 * Function to restart the QEmu daemon, it will recheck the configuration
326
 
 * files and update its state and the networking
327
 
 */
328
 
static int
329
 
networkReload(void) {
330
 
    if (!driverState)
331
 
        return 0;
332
 
 
333
 
    networkDriverLock(driverState);
334
 
    virNetworkLoadAllConfigs(&driverState->networks,
335
 
                             driverState->networkConfigDir,
336
 
                             driverState->networkAutostartDir);
337
 
    networkReloadIptablesRules(driverState);
338
 
    networkAutostartConfigs(driverState);
339
 
    networkDriverUnlock(driverState);
340
 
    return 0;
341
 
}
342
 
 
343
 
/**
344
 
 * networkActive:
345
 
 *
346
 
 * Checks if the QEmu daemon is active, i.e. has an active domain or
347
 
 * an active network
348
 
 *
349
 
 * Returns 1 if active, 0 otherwise
350
 
 */
351
 
static int
352
 
networkActive(void) {
353
 
    unsigned int i;
354
 
    int active = 0;
355
 
 
356
 
    if (!driverState)
357
 
        return 0;
358
 
 
359
 
    networkDriverLock(driverState);
360
 
    for (i = 0 ; i < driverState->networks.count ; i++) {
361
 
        virNetworkObjPtr net = driverState->networks.objs[i];
362
 
        virNetworkObjLock(net);
363
 
        if (virNetworkObjIsActive(net))
364
 
            active = 1;
365
 
        virNetworkObjUnlock(net);
366
 
    }
367
 
    networkDriverUnlock(driverState);
368
 
    return active;
369
 
}
370
 
 
371
 
/**
372
 
 * networkShutdown:
373
 
 *
374
 
 * Shutdown the QEmu daemon, it will stop all active domains and networks
375
 
 */
376
 
static int
377
 
networkShutdown(void) {
378
 
    if (!driverState)
379
 
        return -1;
380
 
 
381
 
    networkDriverLock(driverState);
382
 
 
383
 
    /* free inactive networks */
384
 
    virNetworkObjListFree(&driverState->networks);
385
 
 
386
 
    VIR_FREE(driverState->logDir);
387
 
    VIR_FREE(driverState->networkConfigDir);
388
 
    VIR_FREE(driverState->networkAutostartDir);
389
 
 
390
 
    if (driverState->brctl)
391
 
        brShutdown(driverState->brctl);
392
 
    if (driverState->iptables)
393
 
        iptablesContextFree(driverState->iptables);
394
 
 
395
 
    networkDriverUnlock(driverState);
396
 
    virMutexDestroy(&driverState->lock);
397
 
 
398
 
    VIR_FREE(driverState);
399
 
 
400
 
    return 0;
401
 
}
402
 
 
403
 
 
404
 
static int
405
 
networkSaveDnsmasqHostsfile(virNetworkIpDefPtr ipdef,
406
 
                            dnsmasqContext *dctx,
407
 
                            bool force)
408
 
{
409
 
    unsigned int i;
410
 
 
411
 
    if (! force && virFileExists(dctx->hostsfile->path))
412
 
        return 0;
413
 
 
414
 
    for (i = 0; i < ipdef->nhosts; i++) {
415
 
        virNetworkDHCPHostDefPtr host = &(ipdef->hosts[i]);
416
 
        if ((host->mac) && VIR_SOCKET_HAS_ADDR(&host->ip))
417
 
            dnsmasqAddDhcpHost(dctx, host->mac, &host->ip, host->name);
418
 
    }
419
 
 
420
 
    if (dnsmasqSave(dctx) < 0)
421
 
        return -1;
422
 
 
423
 
    return 0;
424
 
}
425
 
 
426
 
 
427
 
static int
428
 
networkBuildDnsmasqArgv(virNetworkObjPtr network,
429
 
                        virNetworkIpDefPtr ipdef,
430
 
                        const char *pidfile,
431
 
                        virCommandPtr cmd) {
432
 
    int r, ret = -1;
433
 
    int nbleases = 0;
434
 
    char *bridgeaddr;
435
 
    int ii;
436
 
    virNetworkIpDefPtr tmpipdef;
437
 
 
438
 
    if (!(bridgeaddr = virSocketFormatAddr(&ipdef->address)))
439
 
        goto cleanup;
440
 
    /*
441
 
     * NB, be careful about syntax for dnsmasq options in long format.
442
 
     *
443
 
     * If the flag has a mandatory argument, it can be given using
444
 
     * either syntax:
445
 
     *
446
 
     *     --foo bar
447
 
     *     --foo=bar
448
 
     *
449
 
     * If the flag has a optional argument, it *must* be given using
450
 
     * the syntax:
451
 
     *
452
 
     *     --foo=bar
453
 
     *
454
 
     * It is hard to determine whether a flag is optional or not,
455
 
     * without reading the dnsmasq source :-( The manpage is not
456
 
     * very explicit on this.
457
 
     */
458
 
 
459
 
    /*
460
 
     * Needed to ensure dnsmasq uses same algorithm for processing
461
 
     * multiple namedriver entries in /etc/resolv.conf as GLibC.
462
 
     */
463
 
    virCommandAddArgList(cmd, "--strict-order", "--bind-interfaces", NULL);
464
 
 
465
 
    if (network->def->domain)
466
 
        virCommandAddArgList(cmd, "--domain", network->def->domain, NULL);
467
 
 
468
 
    virCommandAddArgPair(cmd, "--pid-file", pidfile);
469
 
 
470
 
    /* *no* conf file */
471
 
    virCommandAddArgList(cmd, "--conf-file=", "", NULL);
472
 
 
473
 
    virCommandAddArgList(cmd,
474
 
                         "--except-interface", "lo",
475
 
                         NULL);
476
 
 
477
 
    /*
478
 
     * --interface does not actually work with dnsmasq < 2.47,
479
 
     * due to DAD for ipv6 addresses on the interface.
480
 
     *
481
 
     * virCommandAddArgList(cmd, "--interface", ipdef->bridge, NULL);
482
 
     *
483
 
     * So listen on all defined IPv[46] addresses
484
 
     */
485
 
    for (ii = 0;
486
 
         (tmpipdef = virNetworkDefGetIpByIndex(network->def, AF_UNSPEC, ii));
487
 
         ii++) {
488
 
        char *ipaddr = virSocketFormatAddr(&tmpipdef->address);
489
 
        if (!ipaddr)
490
 
            goto cleanup;
491
 
        virCommandAddArgList(cmd, "--listen-address", ipaddr, NULL);
492
 
        VIR_FREE(ipaddr);
493
 
    }
494
 
 
495
 
    for (r = 0 ; r < ipdef->nranges ; r++) {
496
 
        char *saddr = virSocketFormatAddr(&ipdef->ranges[r].start);
497
 
        if (!saddr)
498
 
            goto cleanup;
499
 
        char *eaddr = virSocketFormatAddr(&ipdef->ranges[r].end);
500
 
        if (!eaddr) {
501
 
            VIR_FREE(saddr);
502
 
            goto cleanup;
503
 
        }
504
 
        virCommandAddArg(cmd, "--dhcp-range");
505
 
        virCommandAddArgFormat(cmd, "%s,%s", saddr, eaddr);
506
 
        VIR_FREE(saddr);
507
 
        VIR_FREE(eaddr);
508
 
        nbleases += virSocketGetRange(&ipdef->ranges[r].start,
509
 
                                      &ipdef->ranges[r].end);
510
 
    }
511
 
 
512
 
    /*
513
 
     * For static-only DHCP, i.e. with no range but at least one host element,
514
 
     * we have to add a special --dhcp-range option to enable the service in
515
 
     * dnsmasq.
516
 
     */
517
 
    if (!ipdef->nranges && ipdef->nhosts) {
518
 
        virCommandAddArg(cmd, "--dhcp-range");
519
 
        virCommandAddArgFormat(cmd, "%s,static", bridgeaddr);
520
 
    }
521
 
 
522
 
    if (ipdef->nranges > 0) {
523
 
        virCommandAddArgFormat(cmd, "--dhcp-lease-max=%d", nbleases);
524
 
    }
525
 
 
526
 
    if (ipdef->nranges || ipdef->nhosts)
527
 
        virCommandAddArg(cmd, "--dhcp-no-override");
528
 
 
529
 
    if (ipdef->nhosts > 0) {
530
 
        dnsmasqContext *dctx = dnsmasqContextNew(network->def->name,
531
 
                                                 DNSMASQ_STATE_DIR);
532
 
        if (dctx == NULL) {
533
 
            virReportOOMError();
534
 
            goto cleanup;
535
 
        }
536
 
 
537
 
        if (networkSaveDnsmasqHostsfile(ipdef, dctx, false) == 0) {
538
 
            virCommandAddArgPair(cmd, "--dhcp-hostsfile",
539
 
                                 dctx->hostsfile->path);
540
 
        }
541
 
        dnsmasqContextFree(dctx);
542
 
    }
543
 
 
544
 
    if (ipdef->tftproot) {
545
 
        virCommandAddArgList(cmd, "--enable-tftp",
546
 
                             "--tftp-root", ipdef->tftproot,
547
 
                             NULL);
548
 
    }
549
 
    if (ipdef->bootfile) {
550
 
        virCommandAddArg(cmd, "--dhcp-boot");
551
 
        if (VIR_SOCKET_HAS_ADDR(&ipdef->bootserver)) {
552
 
            char *bootserver = virSocketFormatAddr(&ipdef->bootserver);
553
 
 
554
 
            if (!bootserver)
555
 
                goto cleanup;
556
 
            virCommandAddArgFormat(cmd, "%s%s%s",
557
 
                               ipdef->bootfile, ",,", bootserver);
558
 
            VIR_FREE(bootserver);
559
 
        } else {
560
 
            virCommandAddArg(cmd, ipdef->bootfile);
561
 
        }
562
 
    }
563
 
 
564
 
    ret = 0;
565
 
cleanup:
566
 
    VIR_FREE(bridgeaddr);
567
 
    return ret;
568
 
}
569
 
 
570
 
static int
571
 
networkStartDhcpDaemon(virNetworkObjPtr network)
572
 
{
573
 
    virCommandPtr cmd = NULL;
574
 
    char *pidfile = NULL;
575
 
    int ret = -1, err, ii;
576
 
    virNetworkIpDefPtr ipdef;
577
 
 
578
 
    network->dnsmasqPid = -1;
579
 
 
580
 
    /* Look for first IPv4 address that has dhcp defined. */
581
 
    /* We support dhcp config on 1 IPv4 interface only. */
582
 
    for (ii = 0;
583
 
         (ipdef = virNetworkDefGetIpByIndex(network->def, AF_INET, ii));
584
 
         ii++) {
585
 
        if (ipdef->nranges || ipdef->nhosts)
586
 
            break;
587
 
    }
588
 
    if (!ipdef)
589
 
        return 0;
590
 
 
591
 
    if ((err = virFileMakePath(NETWORK_PID_DIR)) != 0) {
592
 
        virReportSystemError(err,
593
 
                             _("cannot create directory %s"),
594
 
                             NETWORK_PID_DIR);
595
 
        goto cleanup;
596
 
    }
597
 
    if ((err = virFileMakePath(NETWORK_STATE_DIR)) != 0) {
598
 
        virReportSystemError(err,
599
 
                             _("cannot create directory %s"),
600
 
                             NETWORK_STATE_DIR);
601
 
        goto cleanup;
602
 
    }
603
 
 
604
 
    if (!(pidfile = virFilePid(NETWORK_PID_DIR, network->def->name))) {
605
 
        virReportOOMError();
606
 
        goto cleanup;
607
 
    }
608
 
 
609
 
    cmd = virCommandNew(DNSMASQ);
610
 
    if (networkBuildDnsmasqArgv(network, ipdef, pidfile, cmd) < 0) {
611
 
        goto cleanup;
612
 
    }
613
 
 
614
 
    if (virCommandRun(cmd, NULL) < 0)
615
 
        goto cleanup;
616
 
 
617
 
    /*
618
 
     * There really is no race here - when dnsmasq daemonizes, its
619
 
     * leader process stays around until its child has actually
620
 
     * written its pidfile. So by time virCommandRun exits it has
621
 
     * waitpid'd and guaranteed the proess has started and written a
622
 
     * pid
623
 
     */
624
 
 
625
 
    if (virFileReadPid(NETWORK_PID_DIR, network->def->name,
626
 
                       &network->dnsmasqPid) < 0)
627
 
        goto cleanup;
628
 
 
629
 
    ret = 0;
630
 
cleanup:
631
 
    VIR_FREE(pidfile);
632
 
    virCommandFree(cmd);
633
 
    return ret;
634
 
}
635
 
 
636
 
static int
637
 
networkStartRadvd(virNetworkObjPtr network)
638
 
{
639
 
    char *pidfile = NULL;
640
 
    char *radvdpidbase = NULL;
641
 
    virBuffer configbuf = VIR_BUFFER_INITIALIZER;;
642
 
    char *configstr = NULL;
643
 
    char *configfile = NULL;
644
 
    virCommandPtr cmd = NULL;
645
 
    int ret = -1, err, ii;
646
 
    virNetworkIpDefPtr ipdef;
647
 
 
648
 
    network->radvdPid = -1;
649
 
 
650
 
    if ((err = virFileMakePath(NETWORK_PID_DIR)) != 0) {
651
 
        virReportSystemError(err,
652
 
                             _("cannot create directory %s"),
653
 
                             NETWORK_PID_DIR);
654
 
        goto cleanup;
655
 
    }
656
 
    if ((err = virFileMakePath(RADVD_STATE_DIR)) != 0) {
657
 
        virReportSystemError(err,
658
 
                             _("cannot create directory %s"),
659
 
                             RADVD_STATE_DIR);
660
 
        goto cleanup;
661
 
    }
662
 
 
663
 
    /* construct pidfile name */
664
 
    if (!(radvdpidbase = networkRadvdPidfileBasename(network->def->name))) {
665
 
        virReportOOMError();
666
 
        goto cleanup;
667
 
    }
668
 
    if (!(pidfile = virFilePid(NETWORK_PID_DIR, radvdpidbase))) {
669
 
        virReportOOMError();
670
 
        goto cleanup;
671
 
    }
672
 
 
673
 
    /* create radvd config file appropriate for this network */
674
 
    virBufferVSprintf(&configbuf, "interface %s\n"
675
 
                      "{\n"
676
 
                      "  AdvSendAdvert on;\n"
677
 
                      "  AdvManagedFlag off;\n"
678
 
                      "  AdvOtherConfigFlag off;\n"
679
 
                      "\n",
680
 
                      network->def->bridge);
681
 
    for (ii = 0;
682
 
         (ipdef = virNetworkDefGetIpByIndex(network->def, AF_INET6, ii));
683
 
         ii++) {
684
 
        int prefix;
685
 
        char *netaddr;
686
 
 
687
 
        prefix = virNetworkIpDefPrefix(ipdef);
688
 
        if (prefix < 0) {
689
 
            networkReportError(VIR_ERR_INTERNAL_ERROR,
690
 
                               _("bridge  '%s' has an invalid prefix"),
691
 
                               network->def->bridge);
692
 
            goto cleanup;
693
 
        }
694
 
        if (!(netaddr = virSocketFormatAddr(&ipdef->address)))
695
 
            goto cleanup;
696
 
        virBufferVSprintf(&configbuf,
697
 
                          "  prefix %s/%d\n"
698
 
                          "  {\n"
699
 
                          "    AdvOnLink on;\n"
700
 
                          "    AdvAutonomous on;\n"
701
 
                          "    AdvRouterAddr off;\n"
702
 
                          "  };\n",
703
 
                          netaddr, prefix);
704
 
        VIR_FREE(netaddr);
705
 
    }
706
 
 
707
 
    virBufferAddLit(&configbuf, "};\n");
708
 
 
709
 
    if (virBufferError(&configbuf)) {
710
 
        virReportOOMError();
711
 
        goto cleanup;
712
 
    }
713
 
    if (!(configstr = virBufferContentAndReset(&configbuf))) {
714
 
        virReportOOMError();
715
 
        goto cleanup;
716
 
    }
717
 
 
718
 
    /* construct the filename */
719
 
    if (!(configfile = networkRadvdConfigFileName(network->def->name))) {
720
 
        virReportOOMError();
721
 
        goto cleanup;
722
 
    }
723
 
    /* write the file */
724
 
    if (virFileWriteStr(configfile, configstr, 0600) < 0) {
725
 
        virReportSystemError(errno,
726
 
                             _("couldn't write radvd config file '%s'"),
727
 
                             configfile);
728
 
        goto cleanup;
729
 
    }
730
 
 
731
 
    /* prevent radvd from daemonizing itself with "--debug 1", and use
732
 
     * a dummy pidfile name - virCommand will create the pidfile we
733
 
     * want to use (this is necessary because radvd's internal
734
 
     * daemonization and pidfile creation causes a race, and the
735
 
     * virFileReadPid() below will fail if we use them).
736
 
     * Unfortunately, it isn't possible to tell radvd to not create
737
 
     * its own pidfile, so we just let it do so, with a slightly
738
 
     * different name. Unused, but harmless.
739
 
     */
740
 
    cmd = virCommandNewArgList(RADVD, "--debug", "1",
741
 
                               "--config", configfile,
742
 
                               "--pidfile", NULL);
743
 
    virCommandAddArgFormat(cmd, "%s-bin", pidfile);
744
 
 
745
 
    virCommandSetPidFile(cmd, pidfile);
746
 
    virCommandDaemonize(cmd);
747
 
 
748
 
    if (virCommandRun(cmd, NULL) < 0)
749
 
        goto cleanup;
750
 
 
751
 
    if (virFileReadPid(NETWORK_PID_DIR, radvdpidbase,
752
 
                       &network->radvdPid) < 0)
753
 
        goto cleanup;
754
 
 
755
 
    ret = 0;
756
 
cleanup:
757
 
    virCommandFree(cmd);
758
 
    VIR_FREE(configfile);
759
 
    VIR_FREE(configstr);
760
 
    virBufferFreeAndReset(&configbuf);
761
 
    VIR_FREE(radvdpidbase);
762
 
    VIR_FREE(pidfile);
763
 
    return ret;
764
 
}
765
 
 
766
 
static int
767
 
networkAddMasqueradingIptablesRules(struct network_driver *driver,
768
 
                                    virNetworkObjPtr network,
769
 
                                    virNetworkIpDefPtr ipdef)
770
 
{
771
 
    int prefix = virNetworkIpDefPrefix(ipdef);
772
 
 
773
 
    if (prefix < 0) {
774
 
        networkReportError(VIR_ERR_INTERNAL_ERROR,
775
 
                           _("Invalid prefix or netmask for '%s'"),
776
 
                           network->def->bridge);
777
 
        goto masqerr1;
778
 
    }
779
 
 
780
 
    /* allow forwarding packets from the bridge interface */
781
 
    if (iptablesAddForwardAllowOut(driver->iptables,
782
 
                                   &ipdef->address,
783
 
                                   prefix,
784
 
                                   network->def->bridge,
785
 
                                   network->def->forwardDev) < 0) {
786
 
        networkReportError(VIR_ERR_SYSTEM_ERROR,
787
 
                           _("failed to add iptables rule to allow forwarding from '%s'"),
788
 
                           network->def->bridge);
789
 
        goto masqerr1;
790
 
    }
791
 
 
792
 
    /* allow forwarding packets to the bridge interface if they are
793
 
     * part of an existing connection
794
 
     */
795
 
    if (iptablesAddForwardAllowRelatedIn(driver->iptables,
796
 
                                         &ipdef->address,
797
 
                                         prefix,
798
 
                                         network->def->bridge,
799
 
                                         network->def->forwardDev) < 0) {
800
 
        networkReportError(VIR_ERR_SYSTEM_ERROR,
801
 
                           _("failed to add iptables rule to allow forwarding to '%s'"),
802
 
                           network->def->bridge);
803
 
        goto masqerr2;
804
 
    }
805
 
 
806
 
    /*
807
 
     * Enable masquerading.
808
 
     *
809
 
     * We need to end up with 3 rules in the table in this order
810
 
     *
811
 
     *  1. protocol=tcp with sport mapping restriction
812
 
     *  2. protocol=udp with sport mapping restriction
813
 
     *  3. generic any protocol
814
 
     *
815
 
     * The sport mappings are required, because default IPtables
816
 
     * MASQUERADE maintain port numbers unchanged where possible.
817
 
     *
818
 
     * NFS can be configured to only "trust" port numbers < 1023.
819
 
     *
820
 
     * Guests using NAT thus need to be prevented from having port
821
 
     * numbers < 1023, otherwise they can bypass the NFS "security"
822
 
     * check on the source port number.
823
 
     *
824
 
     * Since we use '--insert' to add rules to the header of the
825
 
     * chain, we actually need to add them in the reverse of the
826
 
     * order just mentioned !
827
 
     */
828
 
 
829
 
    /* First the generic masquerade rule for other protocols */
830
 
    if (iptablesAddForwardMasquerade(driver->iptables,
831
 
                                     &ipdef->address,
832
 
                                     prefix,
833
 
                                     network->def->forwardDev,
834
 
                                     NULL) < 0) {
835
 
        networkReportError(VIR_ERR_SYSTEM_ERROR,
836
 
                           _("failed to add iptables rule to enable masquerading to '%s'"),
837
 
                           network->def->forwardDev ? network->def->forwardDev : NULL);
838
 
        goto masqerr3;
839
 
    }
840
 
 
841
 
    /* UDP with a source port restriction */
842
 
    if (iptablesAddForwardMasquerade(driver->iptables,
843
 
                                     &ipdef->address,
844
 
                                     prefix,
845
 
                                     network->def->forwardDev,
846
 
                                     "udp") < 0) {
847
 
        networkReportError(VIR_ERR_SYSTEM_ERROR,
848
 
                           _("failed to add iptables rule to enable UDP masquerading to '%s'"),
849
 
                           network->def->forwardDev ? network->def->forwardDev : NULL);
850
 
        goto masqerr4;
851
 
    }
852
 
 
853
 
    /* TCP with a source port restriction */
854
 
    if (iptablesAddForwardMasquerade(driver->iptables,
855
 
                                     &ipdef->address,
856
 
                                     prefix,
857
 
                                     network->def->forwardDev,
858
 
                                     "tcp") < 0) {
859
 
        networkReportError(VIR_ERR_SYSTEM_ERROR,
860
 
                           _("failed to add iptables rule to enable TCP masquerading to '%s'"),
861
 
                           network->def->forwardDev ? network->def->forwardDev : NULL);
862
 
        goto masqerr5;
863
 
    }
864
 
 
865
 
    return 0;
866
 
 
867
 
 masqerr5:
868
 
    iptablesRemoveForwardMasquerade(driver->iptables,
869
 
                                    &ipdef->address,
870
 
                                    prefix,
871
 
                                    network->def->forwardDev,
872
 
                                    "udp");
873
 
 masqerr4:
874
 
    iptablesRemoveForwardMasquerade(driver->iptables,
875
 
                                    &ipdef->address,
876
 
                                    prefix,
877
 
                                    network->def->forwardDev,
878
 
                                    NULL);
879
 
 masqerr3:
880
 
    iptablesRemoveForwardAllowRelatedIn(driver->iptables,
881
 
                                        &ipdef->address,
882
 
                                        prefix,
883
 
                                        network->def->bridge,
884
 
                                        network->def->forwardDev);
885
 
 masqerr2:
886
 
    iptablesRemoveForwardAllowOut(driver->iptables,
887
 
                                  &ipdef->address,
888
 
                                  prefix,
889
 
                                  network->def->bridge,
890
 
                                  network->def->forwardDev);
891
 
 masqerr1:
892
 
    return -1;
893
 
}
894
 
 
895
 
static void
896
 
networkRemoveMasqueradingIptablesRules(struct network_driver *driver,
897
 
                                       virNetworkObjPtr network,
898
 
                                       virNetworkIpDefPtr ipdef)
899
 
{
900
 
    int prefix = virNetworkIpDefPrefix(ipdef);
901
 
 
902
 
    if (prefix >= 0) {
903
 
        iptablesRemoveForwardMasquerade(driver->iptables,
904
 
                                        &ipdef->address,
905
 
                                        prefix,
906
 
                                        network->def->forwardDev,
907
 
                                        "tcp");
908
 
        iptablesRemoveForwardMasquerade(driver->iptables,
909
 
                                        &ipdef->address,
910
 
                                        prefix,
911
 
                                        network->def->forwardDev,
912
 
                                        "udp");
913
 
        iptablesRemoveForwardMasquerade(driver->iptables,
914
 
                                        &ipdef->address,
915
 
                                        prefix,
916
 
                                        network->def->forwardDev,
917
 
                                        NULL);
918
 
 
919
 
        iptablesRemoveForwardAllowRelatedIn(driver->iptables,
920
 
                                            &ipdef->address,
921
 
                                            prefix,
922
 
                                            network->def->bridge,
923
 
                                            network->def->forwardDev);
924
 
        iptablesRemoveForwardAllowOut(driver->iptables,
925
 
                                      &ipdef->address,
926
 
                                      prefix,
927
 
                                      network->def->bridge,
928
 
                                      network->def->forwardDev);
929
 
    }
930
 
}
931
 
 
932
 
static int
933
 
networkAddRoutingIptablesRules(struct network_driver *driver,
934
 
                               virNetworkObjPtr network,
935
 
                               virNetworkIpDefPtr ipdef)
936
 
{
937
 
    int prefix = virNetworkIpDefPrefix(ipdef);
938
 
 
939
 
    if (prefix < 0) {
940
 
        networkReportError(VIR_ERR_INTERNAL_ERROR,
941
 
                           _("Invalid prefix or netmask for '%s'"),
942
 
                           network->def->bridge);
943
 
        goto routeerr1;
944
 
    }
945
 
 
946
 
    /* allow routing packets from the bridge interface */
947
 
    if (iptablesAddForwardAllowOut(driver->iptables,
948
 
                                   &ipdef->address,
949
 
                                   prefix,
950
 
                                   network->def->bridge,
951
 
                                   network->def->forwardDev) < 0) {
952
 
        networkReportError(VIR_ERR_SYSTEM_ERROR,
953
 
                           _("failed to add iptables rule to allow routing from '%s'"),
954
 
                           network->def->bridge);
955
 
        goto routeerr1;
956
 
    }
957
 
 
958
 
    /* allow routing packets to the bridge interface */
959
 
    if (iptablesAddForwardAllowIn(driver->iptables,
960
 
                                  &ipdef->address,
961
 
                                  prefix,
962
 
                                  network->def->bridge,
963
 
                                  network->def->forwardDev) < 0) {
964
 
        networkReportError(VIR_ERR_SYSTEM_ERROR,
965
 
                           _("failed to add iptables rule to allow routing to '%s'"),
966
 
                           network->def->bridge);
967
 
        goto routeerr2;
968
 
    }
969
 
 
970
 
    return 0;
971
 
 
972
 
routeerr2:
973
 
    iptablesRemoveForwardAllowOut(driver->iptables,
974
 
                                  &ipdef->address,
975
 
                                  prefix,
976
 
                                  network->def->bridge,
977
 
                                  network->def->forwardDev);
978
 
routeerr1:
979
 
    return -1;
980
 
}
981
 
 
982
 
static void
983
 
networkRemoveRoutingIptablesRules(struct network_driver *driver,
984
 
                                  virNetworkObjPtr network,
985
 
                                  virNetworkIpDefPtr ipdef)
986
 
{
987
 
    int prefix = virNetworkIpDefPrefix(ipdef);
988
 
 
989
 
    if (prefix >= 0) {
990
 
        iptablesRemoveForwardAllowIn(driver->iptables,
991
 
                                     &ipdef->address,
992
 
                                     prefix,
993
 
                                     network->def->bridge,
994
 
                                     network->def->forwardDev);
995
 
 
996
 
        iptablesRemoveForwardAllowOut(driver->iptables,
997
 
                                      &ipdef->address,
998
 
                                      prefix,
999
 
                                      network->def->bridge,
1000
 
                                      network->def->forwardDev);
1001
 
    }
1002
 
}
1003
 
 
1004
 
/* Add all once/network rules required for IPv6 (if any IPv6 addresses are defined) */
1005
 
static int
1006
 
networkAddGeneralIp6tablesRules(struct network_driver *driver,
1007
 
                               virNetworkObjPtr network)
1008
 
{
1009
 
 
1010
 
    if (!virNetworkDefGetIpByIndex(network->def, AF_INET6, 0))
1011
 
        return 0;
1012
 
 
1013
 
    /* Catch all rules to block forwarding to/from bridges */
1014
 
 
1015
 
    if (iptablesAddForwardRejectOut(driver->iptables, AF_INET6,
1016
 
                                    network->def->bridge) < 0) {
1017
 
        networkReportError(VIR_ERR_SYSTEM_ERROR,
1018
 
                           _("failed to add ip6tables rule to block outbound traffic from '%s'"),
1019
 
                           network->def->bridge);
1020
 
        goto err1;
1021
 
    }
1022
 
 
1023
 
    if (iptablesAddForwardRejectIn(driver->iptables, AF_INET6,
1024
 
                                   network->def->bridge) < 0) {
1025
 
        networkReportError(VIR_ERR_SYSTEM_ERROR,
1026
 
                           _("failed to add ip6tables rule to block inbound traffic to '%s'"),
1027
 
                           network->def->bridge);
1028
 
        goto err2;
1029
 
    }
1030
 
 
1031
 
    /* Allow traffic between guests on the same bridge */
1032
 
    if (iptablesAddForwardAllowCross(driver->iptables, AF_INET6,
1033
 
                                     network->def->bridge) < 0) {
1034
 
        networkReportError(VIR_ERR_SYSTEM_ERROR,
1035
 
                           _("failed to add ip6tables rule to allow cross bridge traffic on '%s'"),
1036
 
                           network->def->bridge);
1037
 
        goto err3;
1038
 
    }
1039
 
 
1040
 
    /* allow DNS over IPv6 */
1041
 
    if (iptablesAddTcpInput(driver->iptables, AF_INET6,
1042
 
                            network->def->bridge, 53) < 0) {
1043
 
        networkReportError(VIR_ERR_SYSTEM_ERROR,
1044
 
                           _("failed to add ip6tables rule to allow DNS requests from '%s'"),
1045
 
                           network->def->bridge);
1046
 
        goto err4;
1047
 
    }
1048
 
 
1049
 
    if (iptablesAddUdpInput(driver->iptables, AF_INET6,
1050
 
                            network->def->bridge, 53) < 0) {
1051
 
        networkReportError(VIR_ERR_SYSTEM_ERROR,
1052
 
                           _("failed to add ip6tables rule to allow DNS requests from '%s'"),
1053
 
                           network->def->bridge);
1054
 
        goto err5;
1055
 
    }
1056
 
 
1057
 
    return 0;
1058
 
 
1059
 
    /* unwind in reverse order from the point of failure */
1060
 
err5:
1061
 
    iptablesRemoveTcpInput(driver->iptables, AF_INET6, network->def->bridge, 53);
1062
 
err4:
1063
 
    iptablesRemoveForwardAllowCross(driver->iptables, AF_INET6, network->def->bridge);
1064
 
err3:
1065
 
    iptablesRemoveForwardRejectIn(driver->iptables, AF_INET6, network->def->bridge);
1066
 
err2:
1067
 
    iptablesRemoveForwardRejectOut(driver->iptables, AF_INET6, network->def->bridge);
1068
 
err1:
1069
 
    return -1;
1070
 
}
1071
 
 
1072
 
static void
1073
 
networkRemoveGeneralIp6tablesRules(struct network_driver *driver,
1074
 
                                  virNetworkObjPtr network)
1075
 
{
1076
 
    if (!virNetworkDefGetIpByIndex(network->def, AF_INET6, 0))
1077
 
        return;
1078
 
 
1079
 
    iptablesRemoveForwardAllowCross(driver->iptables, AF_INET6, network->def->bridge);
1080
 
    iptablesRemoveForwardRejectIn(driver->iptables, AF_INET6, network->def->bridge);
1081
 
    iptablesRemoveForwardRejectOut(driver->iptables, AF_INET6, network->def->bridge);
1082
 
}
1083
 
 
1084
 
static int
1085
 
networkAddGeneralIptablesRules(struct network_driver *driver,
1086
 
                               virNetworkObjPtr network)
1087
 
{
1088
 
    int ii;
1089
 
    virNetworkIpDefPtr ipv4def;
1090
 
 
1091
 
    /* First look for first IPv4 address that has dhcp or tftpboot defined. */
1092
 
    /* We support dhcp config on 1 IPv4 interface only. */
1093
 
    for (ii = 0;
1094
 
         (ipv4def = virNetworkDefGetIpByIndex(network->def, AF_INET, ii));
1095
 
         ii++) {
1096
 
        if (ipv4def->nranges || ipv4def->nhosts || ipv4def->tftproot)
1097
 
            break;
1098
 
    }
1099
 
 
1100
 
    /* allow DHCP requests through to dnsmasq */
1101
 
 
1102
 
    if (iptablesAddTcpInput(driver->iptables, AF_INET,
1103
 
                            network->def->bridge, 67) < 0) {
1104
 
        networkReportError(VIR_ERR_SYSTEM_ERROR,
1105
 
                           _("failed to add iptables rule to allow DHCP requests from '%s'"),
1106
 
                           network->def->bridge);
1107
 
        goto err1;
1108
 
    }
1109
 
 
1110
 
    if (iptablesAddUdpInput(driver->iptables, AF_INET,
1111
 
                            network->def->bridge, 67) < 0) {
1112
 
        networkReportError(VIR_ERR_SYSTEM_ERROR,
1113
 
                           _("failed to add iptables rule to allow DHCP requests from '%s'"),
1114
 
                           network->def->bridge);
1115
 
        goto err2;
1116
 
    }
1117
 
 
1118
 
    /* If we are doing local DHCP service on this network, attempt to
1119
 
     * add a rule that will fixup the checksum of DHCP response
1120
 
     * packets back to the guests (but report failure without
1121
 
     * aborting, since not all iptables implementations support it).
1122
 
     */
1123
 
 
1124
 
    if (ipv4def && (ipv4def->nranges || ipv4def->nhosts) &&
1125
 
        (iptablesAddOutputFixUdpChecksum(driver->iptables,
1126
 
                                         network->def->bridge, 68) < 0)) {
1127
 
        VIR_WARN("Could not add rule to fixup DHCP response checksums "
1128
 
                 "on network '%s'.", network->def->name);
1129
 
        VIR_WARN0("May need to update iptables package & kernel to support CHECKSUM rule.");
1130
 
    }
1131
 
 
1132
 
    /* allow DNS requests through to dnsmasq */
1133
 
    if (iptablesAddTcpInput(driver->iptables, AF_INET,
1134
 
                            network->def->bridge, 53) < 0) {
1135
 
        networkReportError(VIR_ERR_SYSTEM_ERROR,
1136
 
                           _("failed to add iptables rule to allow DNS requests from '%s'"),
1137
 
                           network->def->bridge);
1138
 
        goto err3;
1139
 
    }
1140
 
 
1141
 
    if (iptablesAddUdpInput(driver->iptables, AF_INET,
1142
 
                            network->def->bridge, 53) < 0) {
1143
 
        networkReportError(VIR_ERR_SYSTEM_ERROR,
1144
 
                           _("failed to add iptables rule to allow DNS requests from '%s'"),
1145
 
                           network->def->bridge);
1146
 
        goto err4;
1147
 
    }
1148
 
 
1149
 
    /* allow TFTP requests through to dnsmasq if necessary */
1150
 
    if (ipv4def && ipv4def->tftproot &&
1151
 
        iptablesAddUdpInput(driver->iptables, AF_INET,
1152
 
                            network->def->bridge, 69) < 0) {
1153
 
        networkReportError(VIR_ERR_SYSTEM_ERROR,
1154
 
                           _("failed to add iptables rule to allow TFTP requests from '%s'"),
1155
 
                           network->def->bridge);
1156
 
        goto err5;
1157
 
    }
1158
 
 
1159
 
    /* Catch all rules to block forwarding to/from bridges */
1160
 
 
1161
 
    if (iptablesAddForwardRejectOut(driver->iptables, AF_INET,
1162
 
                                    network->def->bridge) < 0) {
1163
 
        networkReportError(VIR_ERR_SYSTEM_ERROR,
1164
 
                           _("failed to add iptables rule to block outbound traffic from '%s'"),
1165
 
                           network->def->bridge);
1166
 
        goto err6;
1167
 
    }
1168
 
 
1169
 
    if (iptablesAddForwardRejectIn(driver->iptables, AF_INET,
1170
 
                                   network->def->bridge) < 0) {
1171
 
        networkReportError(VIR_ERR_SYSTEM_ERROR,
1172
 
                           _("failed to add iptables rule to block inbound traffic to '%s'"),
1173
 
                           network->def->bridge);
1174
 
        goto err7;
1175
 
    }
1176
 
 
1177
 
    /* Allow traffic between guests on the same bridge */
1178
 
    if (iptablesAddForwardAllowCross(driver->iptables, AF_INET,
1179
 
                                     network->def->bridge) < 0) {
1180
 
        networkReportError(VIR_ERR_SYSTEM_ERROR,
1181
 
                           _("failed to add iptables rule to allow cross bridge traffic on '%s'"),
1182
 
                           network->def->bridge);
1183
 
        goto err8;
1184
 
    }
1185
 
 
1186
 
    /* add IPv6 general rules, if needed */
1187
 
    if (networkAddGeneralIp6tablesRules(driver, network) < 0) {
1188
 
        goto err9;
1189
 
    }
1190
 
 
1191
 
    return 0;
1192
 
 
1193
 
    /* unwind in reverse order from the point of failure */
1194
 
err9:
1195
 
    iptablesRemoveForwardAllowCross(driver->iptables, AF_INET, network->def->bridge);
1196
 
err8:
1197
 
    iptablesRemoveForwardRejectIn(driver->iptables, AF_INET, network->def->bridge);
1198
 
err7:
1199
 
    iptablesRemoveForwardRejectOut(driver->iptables, AF_INET, network->def->bridge);
1200
 
err6:
1201
 
    if (ipv4def && ipv4def->tftproot) {
1202
 
        iptablesRemoveUdpInput(driver->iptables, AF_INET, network->def->bridge, 69);
1203
 
    }
1204
 
err5:
1205
 
    iptablesRemoveUdpInput(driver->iptables, AF_INET, network->def->bridge, 53);
1206
 
err4:
1207
 
    iptablesRemoveTcpInput(driver->iptables, AF_INET, network->def->bridge, 53);
1208
 
err3:
1209
 
    iptablesRemoveUdpInput(driver->iptables, AF_INET, network->def->bridge, 67);
1210
 
err2:
1211
 
    iptablesRemoveTcpInput(driver->iptables, AF_INET, network->def->bridge, 67);
1212
 
err1:
1213
 
    return -1;
1214
 
}
1215
 
 
1216
 
static void
1217
 
networkRemoveGeneralIptablesRules(struct network_driver *driver,
1218
 
                                  virNetworkObjPtr network)
1219
 
{
1220
 
    int ii;
1221
 
    virNetworkIpDefPtr ipv4def;
1222
 
 
1223
 
    networkRemoveGeneralIp6tablesRules(driver, network);
1224
 
 
1225
 
    for (ii = 0;
1226
 
         (ipv4def = virNetworkDefGetIpByIndex(network->def, AF_INET, ii));
1227
 
         ii++) {
1228
 
        if (ipv4def->nranges || ipv4def->nhosts || ipv4def->tftproot)
1229
 
            break;
1230
 
    }
1231
 
 
1232
 
    iptablesRemoveForwardAllowCross(driver->iptables, AF_INET, network->def->bridge);
1233
 
    iptablesRemoveForwardRejectIn(driver->iptables, AF_INET, network->def->bridge);
1234
 
    iptablesRemoveForwardRejectOut(driver->iptables, AF_INET, network->def->bridge);
1235
 
    if (ipv4def && ipv4def->tftproot) {
1236
 
        iptablesRemoveUdpInput(driver->iptables, AF_INET, network->def->bridge, 69);
1237
 
    }
1238
 
    iptablesRemoveUdpInput(driver->iptables, AF_INET, network->def->bridge, 53);
1239
 
    iptablesRemoveTcpInput(driver->iptables, AF_INET, network->def->bridge, 53);
1240
 
    if (ipv4def && (ipv4def->nranges || ipv4def->nhosts)) {
1241
 
        iptablesRemoveOutputFixUdpChecksum(driver->iptables,
1242
 
                                           network->def->bridge, 68);
1243
 
    }
1244
 
    iptablesRemoveUdpInput(driver->iptables, AF_INET, network->def->bridge, 67);
1245
 
    iptablesRemoveTcpInput(driver->iptables, AF_INET, network->def->bridge, 67);
1246
 
}
1247
 
 
1248
 
static int
1249
 
networkAddIpSpecificIptablesRules(struct network_driver *driver,
1250
 
                                  virNetworkObjPtr network,
1251
 
                                  virNetworkIpDefPtr ipdef)
1252
 
{
1253
 
    /* NB: in the case of IPv6, routing rules are added when the
1254
 
     * forward mode is NAT. This is because IPv6 has no NAT.
1255
 
     */
1256
 
 
1257
 
    if (network->def->forwardType == VIR_NETWORK_FORWARD_NAT) {
1258
 
        if (VIR_SOCKET_IS_FAMILY(&ipdef->address, AF_INET))
1259
 
            return networkAddMasqueradingIptablesRules(driver, network, ipdef);
1260
 
        else if (VIR_SOCKET_IS_FAMILY(&ipdef->address, AF_INET6))
1261
 
            return networkAddRoutingIptablesRules(driver, network, ipdef);
1262
 
    } else if (network->def->forwardType == VIR_NETWORK_FORWARD_ROUTE) {
1263
 
        return networkAddRoutingIptablesRules(driver, network, ipdef);
1264
 
    }
1265
 
    return 0;
1266
 
}
1267
 
 
1268
 
static void
1269
 
networkRemoveIpSpecificIptablesRules(struct network_driver *driver,
1270
 
                                     virNetworkObjPtr network,
1271
 
                                     virNetworkIpDefPtr ipdef)
1272
 
{
1273
 
    if (network->def->forwardType == VIR_NETWORK_FORWARD_NAT) {
1274
 
        if (VIR_SOCKET_IS_FAMILY(&ipdef->address, AF_INET))
1275
 
            networkRemoveMasqueradingIptablesRules(driver, network, ipdef);
1276
 
        else if (VIR_SOCKET_IS_FAMILY(&ipdef->address, AF_INET6))
1277
 
            networkRemoveRoutingIptablesRules(driver, network, ipdef);
1278
 
    } else if (network->def->forwardType == VIR_NETWORK_FORWARD_ROUTE) {
1279
 
        networkRemoveRoutingIptablesRules(driver, network, ipdef);
1280
 
    }
1281
 
}
1282
 
 
1283
 
/* Add all rules for all ip addresses (and general rules) on a network */
1284
 
static int
1285
 
networkAddIptablesRules(struct network_driver *driver,
1286
 
                        virNetworkObjPtr network)
1287
 
{
1288
 
    int ii;
1289
 
    virNetworkIpDefPtr ipdef;
1290
 
 
1291
 
    /* Add "once per network" rules */
1292
 
    if (networkAddGeneralIptablesRules(driver, network) < 0)
1293
 
        return -1;
1294
 
 
1295
 
    for (ii = 0;
1296
 
         (ipdef = virNetworkDefGetIpByIndex(network->def, AF_UNSPEC, ii));
1297
 
         ii++) {
1298
 
        /* Add address-specific iptables rules */
1299
 
        if (networkAddIpSpecificIptablesRules(driver, network, ipdef) < 0) {
1300
 
            goto err;
1301
 
        }
1302
 
    }
1303
 
    return 0;
1304
 
 
1305
 
err:
1306
 
    /* The final failed call to networkAddIpSpecificIptablesRules will
1307
 
     * have removed any rules it created, but we need to remove those
1308
 
     * added for previous IP addresses.
1309
 
     */
1310
 
    while ((--ii >= 0) &&
1311
 
           (ipdef = virNetworkDefGetIpByIndex(network->def, AF_UNSPEC, ii))) {
1312
 
        networkRemoveIpSpecificIptablesRules(driver, network, ipdef);
1313
 
    }
1314
 
    networkRemoveGeneralIptablesRules(driver, network);
1315
 
    return -1;
1316
 
}
1317
 
 
1318
 
/* Remove all rules for all ip addresses (and general rules) on a network */
1319
 
static void
1320
 
networkRemoveIptablesRules(struct network_driver *driver,
1321
 
                           virNetworkObjPtr network)
1322
 
{
1323
 
    int ii;
1324
 
    virNetworkIpDefPtr ipdef;
1325
 
 
1326
 
    for (ii = 0;
1327
 
         (ipdef = virNetworkDefGetIpByIndex(network->def, AF_UNSPEC, ii));
1328
 
         ii++) {
1329
 
        networkRemoveIpSpecificIptablesRules(driver, network, ipdef);
1330
 
    }
1331
 
    networkRemoveGeneralIptablesRules(driver, network);
1332
 
}
1333
 
 
1334
 
static void
1335
 
networkReloadIptablesRules(struct network_driver *driver)
1336
 
{
1337
 
    unsigned int i;
1338
 
 
1339
 
    VIR_INFO0(_("Reloading iptables rules"));
1340
 
 
1341
 
    for (i = 0 ; i < driver->networks.count ; i++) {
1342
 
        virNetworkObjLock(driver->networks.objs[i]);
1343
 
        if (virNetworkObjIsActive(driver->networks.objs[i])) {
1344
 
            networkRemoveIptablesRules(driver, driver->networks.objs[i]);
1345
 
            if (networkAddIptablesRules(driver, driver->networks.objs[i]) < 0) {
1346
 
                /* failed to add but already logged */
1347
 
            }
1348
 
        }
1349
 
        virNetworkObjUnlock(driver->networks.objs[i]);
1350
 
    }
1351
 
}
1352
 
 
1353
 
/* Enable IP Forwarding. Return 0 for success, -1 for failure. */
1354
 
static int
1355
 
networkEnableIpForwarding(bool enableIPv4, bool enableIPv6)
1356
 
{
1357
 
    int ret = 0;
1358
 
    if (enableIPv4)
1359
 
        ret = virFileWriteStr("/proc/sys/net/ipv4/ip_forward", "1\n", 0);
1360
 
    if (enableIPv6 && ret == 0)
1361
 
        ret = virFileWriteStr("/proc/sys/net/ipv6/conf/all/forwarding", "1\n", 0);
1362
 
    return ret;
1363
 
}
1364
 
 
1365
 
#define SYSCTL_PATH "/proc/sys"
1366
 
 
1367
 
static int
1368
 
networkSetIPv6Sysctls(virNetworkObjPtr network)
1369
 
{
1370
 
    char *field = NULL;
1371
 
    int ret = -1;
1372
 
 
1373
 
    if (!virNetworkDefGetIpByIndex(network->def, AF_INET6, 0)) {
1374
 
        /* Only set disable_ipv6 if there are no ipv6 addresses defined for
1375
 
         * the network.
1376
 
         */
1377
 
        if (virAsprintf(&field, SYSCTL_PATH "/net/ipv6/conf/%s/disable_ipv6",
1378
 
                        network->def->bridge) < 0) {
1379
 
            virReportOOMError();
1380
 
            goto cleanup;
1381
 
        }
1382
 
 
1383
 
        if (access(field, W_OK) < 0 && errno == ENOENT) {
1384
 
            VIR_DEBUG("ipv6 appears to already be disabled on %s",
1385
 
                      network->def->bridge);
1386
 
            ret = 0;
1387
 
            goto cleanup;
1388
 
        }
1389
 
 
1390
 
        if (virFileWriteStr(field, "1", 0) < 0) {
1391
 
            virReportSystemError(errno,
1392
 
                                 _("cannot write to %s to disable IPv6 on bridge %s"),
1393
 
                                 field, network->def->bridge);
1394
 
            goto cleanup;
1395
 
        }
1396
 
        VIR_FREE(field);
1397
 
    }
1398
 
 
1399
 
    /* The rest of the ipv6 sysctl tunables should always be set,
1400
 
     * whether or not we're using ipv6 on this bridge.
1401
 
     */
1402
 
 
1403
 
    /* Prevent guests from hijacking the host network by sending out
1404
 
     * their own router advertisements.
1405
 
     */
1406
 
    if (virAsprintf(&field, SYSCTL_PATH "/net/ipv6/conf/%s/accept_ra",
1407
 
                    network->def->bridge) < 0) {
1408
 
        virReportOOMError();
1409
 
        goto cleanup;
1410
 
    }
1411
 
 
1412
 
    if (virFileWriteStr(field, "0", 0) < 0) {
1413
 
        virReportSystemError(errno,
1414
 
                             _("cannot disable %s"), field);
1415
 
        goto cleanup;
1416
 
    }
1417
 
    VIR_FREE(field);
1418
 
 
1419
 
    /* All interfaces used as a gateway (which is what this is, by
1420
 
     * definition), must always have autoconf=0.
1421
 
     */
1422
 
    if (virAsprintf(&field, SYSCTL_PATH "/net/ipv6/conf/%s/autoconf",
1423
 
                    network->def->bridge) < 0) {
1424
 
        virReportOOMError();
1425
 
        goto cleanup;
1426
 
    }
1427
 
 
1428
 
    if (virFileWriteStr(field, "1", 0) < 0) {
1429
 
        virReportSystemError(errno,
1430
 
                             _("cannot enable %s"), field);
1431
 
        goto cleanup;
1432
 
    }
1433
 
 
1434
 
    ret = 0;
1435
 
cleanup:
1436
 
    VIR_FREE(field);
1437
 
    return ret;
1438
 
}
1439
 
 
1440
 
#define PROC_NET_ROUTE "/proc/net/route"
1441
 
 
1442
 
/* XXX: This function can be a lot more exhaustive, there are certainly
1443
 
 *      other scenarios where we can ruin host network connectivity.
1444
 
 * XXX: Using a proper library is preferred over parsing /proc
1445
 
 */
1446
 
static int
1447
 
networkCheckRouteCollision(virNetworkObjPtr network)
1448
 
{
1449
 
    int ret = 0, len;
1450
 
    char *cur, *buf = NULL;
1451
 
    enum {MAX_ROUTE_SIZE = 1024*64};
1452
 
 
1453
 
    /* Read whole routing table into memory */
1454
 
    if ((len = virFileReadAll(PROC_NET_ROUTE, MAX_ROUTE_SIZE, &buf)) < 0)
1455
 
        goto out;
1456
 
 
1457
 
    /* Dropping the last character shouldn't hurt */
1458
 
    if (len > 0)
1459
 
        buf[len-1] = '\0';
1460
 
 
1461
 
    VIR_DEBUG("%s output:\n%s", PROC_NET_ROUTE, buf);
1462
 
 
1463
 
    if (!STRPREFIX (buf, "Iface"))
1464
 
        goto out;
1465
 
 
1466
 
    /* First line is just headings, skip it */
1467
 
    cur = strchr(buf, '\n');
1468
 
    if (cur)
1469
 
        cur++;
1470
 
 
1471
 
    while (cur) {
1472
 
        char iface[17], dest[128], mask[128];
1473
 
        unsigned int addr_val, mask_val;
1474
 
        virNetworkIpDefPtr ipdef;
1475
 
        int num, ii;
1476
 
 
1477
 
        /* NUL-terminate the line, so sscanf doesn't go beyond a newline.  */
1478
 
        char *nl = strchr(cur, '\n');
1479
 
        if (nl) {
1480
 
            *nl++ = '\0';
1481
 
        }
1482
 
 
1483
 
        num = sscanf(cur, "%16s %127s %*s %*s %*s %*s %*s %127s",
1484
 
                     iface, dest, mask);
1485
 
        cur = nl;
1486
 
 
1487
 
        if (num != 3) {
1488
 
            VIR_DEBUG("Failed to parse %s", PROC_NET_ROUTE);
1489
 
            continue;
1490
 
        }
1491
 
 
1492
 
        if (virStrToLong_ui(dest, NULL, 16, &addr_val) < 0) {
1493
 
            VIR_DEBUG("Failed to convert network address %s to uint", dest);
1494
 
            continue;
1495
 
        }
1496
 
 
1497
 
        if (virStrToLong_ui(mask, NULL, 16, &mask_val) < 0) {
1498
 
            VIR_DEBUG("Failed to convert network mask %s to uint", mask);
1499
 
            continue;
1500
 
        }
1501
 
 
1502
 
        addr_val &= mask_val;
1503
 
 
1504
 
        for (ii = 0;
1505
 
             (ipdef = virNetworkDefGetIpByIndex(network->def, AF_INET, ii));
1506
 
             ii++) {
1507
 
 
1508
 
            unsigned int net_dest;
1509
 
            virSocketAddr netmask;
1510
 
 
1511
 
            if (virNetworkIpDefNetmask(ipdef, &netmask) < 0) {
1512
 
                VIR_WARN("Failed to get netmask of '%s'",
1513
 
                         network->def->bridge);
1514
 
                continue;
1515
 
            }
1516
 
 
1517
 
            net_dest = (ipdef->address.data.inet4.sin_addr.s_addr &
1518
 
                        netmask.data.inet4.sin_addr.s_addr);
1519
 
 
1520
 
            if ((net_dest == addr_val) &&
1521
 
                (netmask.data.inet4.sin_addr.s_addr == mask_val)) {
1522
 
                networkReportError(VIR_ERR_INTERNAL_ERROR,
1523
 
                                   _("Network is already in use by interface %s"),
1524
 
                                   iface);
1525
 
                ret = -1;
1526
 
                goto out;
1527
 
            }
1528
 
        }
1529
 
    }
1530
 
 
1531
 
out:
1532
 
    VIR_FREE(buf);
1533
 
    return ret;
1534
 
}
1535
 
 
1536
 
static int
1537
 
networkAddAddrToBridge(struct network_driver *driver,
1538
 
                       virNetworkObjPtr network,
1539
 
                       virNetworkIpDefPtr ipdef)
1540
 
{
1541
 
    int prefix = virNetworkIpDefPrefix(ipdef);
1542
 
 
1543
 
    if (prefix < 0) {
1544
 
        networkReportError(VIR_ERR_INTERNAL_ERROR,
1545
 
                           _("bridge '%s' has an invalid netmask or IP address"),
1546
 
                           network->def->bridge);
1547
 
        return -1;
1548
 
    }
1549
 
 
1550
 
    if (brAddInetAddress(driver->brctl, network->def->bridge,
1551
 
                         &ipdef->address, prefix) < 0) {
1552
 
        networkReportError(VIR_ERR_INTERNAL_ERROR,
1553
 
                           _("cannot set IP address on bridge '%s'"),
1554
 
                           network->def->bridge);
1555
 
        return -1;
1556
 
    }
1557
 
 
1558
 
    return 0;
1559
 
}
1560
 
 
1561
 
static int
1562
 
networkStartNetworkDaemon(struct network_driver *driver,
1563
 
                          virNetworkObjPtr network)
1564
 
{
1565
 
    int ii, err;
1566
 
    bool v4present = false, v6present = false;
1567
 
    virErrorPtr save_err = NULL;
1568
 
    virNetworkIpDefPtr ipdef;
1569
 
 
1570
 
    if (virNetworkObjIsActive(network)) {
1571
 
        networkReportError(VIR_ERR_OPERATION_INVALID,
1572
 
                           "%s", _("network is already active"));
1573
 
        return -1;
1574
 
    }
1575
 
 
1576
 
    /* Check to see if any network IP collides with an existing route */
1577
 
    if (networkCheckRouteCollision(network) < 0)
1578
 
        return -1;
1579
 
 
1580
 
    /* Create and configure the bridge device */
1581
 
    if ((err = brAddBridge(driver->brctl, network->def->bridge))) {
1582
 
        virReportSystemError(err,
1583
 
                             _("cannot create bridge '%s'"),
1584
 
                             network->def->bridge);
1585
 
        return -1;
1586
 
    }
1587
 
 
1588
 
    /* Set bridge options */
1589
 
    if (brSetForwardDelay(driver->brctl, network->def->bridge,
1590
 
                          network->def->delay)) {
1591
 
        networkReportError(VIR_ERR_INTERNAL_ERROR,
1592
 
                           _("cannot set forward delay on bridge '%s'"),
1593
 
                           network->def->bridge);
1594
 
        goto err1;
1595
 
    }
1596
 
 
1597
 
    if (brSetEnableSTP(driver->brctl, network->def->bridge,
1598
 
                       network->def->stp ? 1 : 0)) {
1599
 
        networkReportError(VIR_ERR_INTERNAL_ERROR,
1600
 
                           _("cannot set STP '%s' on bridge '%s'"),
1601
 
                           network->def->stp ? "on" : "off", network->def->bridge);
1602
 
        goto err1;
1603
 
    }
1604
 
 
1605
 
    /* Disable IPv6 on the bridge if there are no IPv6 addresses
1606
 
     * defined, and set other IPv6 sysctl tunables appropriately.
1607
 
     */
1608
 
    if (networkSetIPv6Sysctls(network) < 0)
1609
 
        goto err1;
1610
 
 
1611
 
    /* Add "once per network" rules */
1612
 
    if (networkAddIptablesRules(driver, network) < 0)
1613
 
        goto err1;
1614
 
 
1615
 
    for (ii = 0;
1616
 
         (ipdef = virNetworkDefGetIpByIndex(network->def, AF_UNSPEC, ii));
1617
 
         ii++) {
1618
 
        if (VIR_SOCKET_IS_FAMILY(&ipdef->address, AF_INET))
1619
 
            v4present = true;
1620
 
        if (VIR_SOCKET_IS_FAMILY(&ipdef->address, AF_INET6))
1621
 
            v6present = true;
1622
 
 
1623
 
        /* Add the IP address/netmask to the bridge */
1624
 
        if (networkAddAddrToBridge(driver, network, ipdef) < 0) {
1625
 
            goto err2;
1626
 
        }
1627
 
    }
1628
 
 
1629
 
    /* Bring up the bridge interface */
1630
 
    if ((err = brSetInterfaceUp(driver->brctl, network->def->bridge, 1))) {
1631
 
        virReportSystemError(err,
1632
 
                             _("failed to bring the bridge '%s' up"),
1633
 
                             network->def->bridge);
1634
 
        goto err2;
1635
 
    }
1636
 
 
1637
 
    /* If forwardType != NONE, turn on global IP forwarding */
1638
 
    if (network->def->forwardType != VIR_NETWORK_FORWARD_NONE &&
1639
 
        networkEnableIpForwarding(v4present, v6present) < 0) {
1640
 
        virReportSystemError(errno, "%s",
1641
 
                             _("failed to enable IP forwarding"));
1642
 
        goto err3;
1643
 
    }
1644
 
 
1645
 
 
1646
 
    /* start dnsmasq if there are any IPv4 addresses */
1647
 
    if (v4present && networkStartDhcpDaemon(network) < 0)
1648
 
        goto err3;
1649
 
 
1650
 
    /* start radvd if there are any ipv6 addresses */
1651
 
    if (v6present && networkStartRadvd(network) < 0)
1652
 
        goto err4;
1653
 
 
1654
 
    /* Persist the live configuration now we have bridge info  */
1655
 
    if (virNetworkSaveConfig(NETWORK_STATE_DIR, network->def) < 0) {
1656
 
        goto err5;
1657
 
    }
1658
 
 
1659
 
    network->active = 1;
1660
 
 
1661
 
    return 0;
1662
 
 
1663
 
 err5:
1664
 
    if (!save_err)
1665
 
        save_err = virSaveLastError();
1666
 
 
1667
 
    if (network->radvdPid > 0) {
1668
 
        kill(network->radvdPid, SIGTERM);
1669
 
        network->radvdPid = -1;
1670
 
    }
1671
 
 
1672
 
 err4:
1673
 
    if (!save_err)
1674
 
        save_err = virSaveLastError();
1675
 
 
1676
 
    if (network->dnsmasqPid > 0) {
1677
 
        kill(network->dnsmasqPid, SIGTERM);
1678
 
        network->dnsmasqPid = -1;
1679
 
    }
1680
 
 
1681
 
 err3:
1682
 
    if (!save_err)
1683
 
        save_err = virSaveLastError();
1684
 
    if ((err = brSetInterfaceUp(driver->brctl, network->def->bridge, 0))) {
1685
 
        char ebuf[1024];
1686
 
        VIR_WARN("Failed to bring down bridge '%s' : %s",
1687
 
                 network->def->bridge, virStrerror(err, ebuf, sizeof ebuf));
1688
 
    }
1689
 
 
1690
 
 err2:
1691
 
    if (!save_err)
1692
 
        save_err = virSaveLastError();
1693
 
    networkRemoveIptablesRules(driver, network);
1694
 
 
1695
 
 err1:
1696
 
    if (!save_err)
1697
 
        save_err = virSaveLastError();
1698
 
    if ((err = brDeleteBridge(driver->brctl, network->def->bridge))) {
1699
 
        char ebuf[1024];
1700
 
        VIR_WARN("Failed to delete bridge '%s' : %s",
1701
 
                 network->def->bridge, virStrerror(err, ebuf, sizeof ebuf));
1702
 
    }
1703
 
 
1704
 
    if (save_err) {
1705
 
        virSetError(save_err);
1706
 
        virFreeError(save_err);
1707
 
    }
1708
 
    return -1;
1709
 
}
1710
 
 
1711
 
 
1712
 
static int networkShutdownNetworkDaemon(struct network_driver *driver,
1713
 
                                        virNetworkObjPtr network)
1714
 
{
1715
 
    int err;
1716
 
    char *stateFile;
1717
 
 
1718
 
    VIR_INFO(_("Shutting down network '%s'"), network->def->name);
1719
 
 
1720
 
    if (!virNetworkObjIsActive(network))
1721
 
        return 0;
1722
 
 
1723
 
    stateFile = virNetworkConfigFile(NETWORK_STATE_DIR, network->def->name);
1724
 
    if (!stateFile)
1725
 
        return -1;
1726
 
 
1727
 
    unlink(stateFile);
1728
 
    VIR_FREE(stateFile);
1729
 
 
1730
 
    if (network->radvdPid > 0) {
1731
 
        char *radvdpidbase;
1732
 
 
1733
 
        kill(network->radvdPid, SIGTERM);
1734
 
        /* attempt to delete the pidfile we created */
1735
 
        if (!(radvdpidbase = networkRadvdPidfileBasename(network->def->name))) {
1736
 
            virReportOOMError();
1737
 
        } else {
1738
 
            virFileDeletePid(NETWORK_PID_DIR, radvdpidbase);
1739
 
            VIR_FREE(radvdpidbase);
1740
 
        }
1741
 
    }
1742
 
 
1743
 
    if (network->dnsmasqPid > 0)
1744
 
        kill(network->dnsmasqPid, SIGTERM);
1745
 
 
1746
 
    char ebuf[1024];
1747
 
    if ((err = brSetInterfaceUp(driver->brctl, network->def->bridge, 0))) {
1748
 
        VIR_WARN("Failed to bring down bridge '%s' : %s",
1749
 
                 network->def->bridge, virStrerror(err, ebuf, sizeof ebuf));
1750
 
    }
1751
 
 
1752
 
    networkRemoveIptablesRules(driver, network);
1753
 
 
1754
 
    if ((err = brDeleteBridge(driver->brctl, network->def->bridge))) {
1755
 
        VIR_WARN("Failed to delete bridge '%s' : %s",
1756
 
                 network->def->bridge, virStrerror(err, ebuf, sizeof ebuf));
1757
 
    }
1758
 
 
1759
 
    /* See if its still alive and really really kill it */
1760
 
    if (network->dnsmasqPid > 0 &&
1761
 
        (kill(network->dnsmasqPid, 0) == 0))
1762
 
        kill(network->dnsmasqPid, SIGKILL);
1763
 
    network->dnsmasqPid = -1;
1764
 
 
1765
 
    if (network->radvdPid > 0 &&
1766
 
        (kill(network->radvdPid, 0) == 0))
1767
 
        kill(network->radvdPid, SIGKILL);
1768
 
    network->radvdPid = -1;
1769
 
 
1770
 
    network->active = 0;
1771
 
 
1772
 
    if (network->newDef) {
1773
 
        virNetworkDefFree(network->def);
1774
 
        network->def = network->newDef;
1775
 
        network->newDef = NULL;
1776
 
    }
1777
 
 
1778
 
    return 0;
1779
 
}
1780
 
 
1781
 
 
1782
 
static virNetworkPtr networkLookupByUUID(virConnectPtr conn,
1783
 
                                         const unsigned char *uuid) {
1784
 
    struct network_driver *driver = conn->networkPrivateData;
1785
 
    virNetworkObjPtr network;
1786
 
    virNetworkPtr ret = NULL;
1787
 
 
1788
 
    networkDriverLock(driver);
1789
 
    network = virNetworkFindByUUID(&driver->networks, uuid);
1790
 
    networkDriverUnlock(driver);
1791
 
    if (!network) {
1792
 
        networkReportError(VIR_ERR_NO_NETWORK,
1793
 
                           "%s", _("no network with matching uuid"));
1794
 
        goto cleanup;
1795
 
    }
1796
 
 
1797
 
    ret = virGetNetwork(conn, network->def->name, network->def->uuid);
1798
 
 
1799
 
cleanup:
1800
 
    if (network)
1801
 
        virNetworkObjUnlock(network);
1802
 
    return ret;
1803
 
}
1804
 
 
1805
 
static virNetworkPtr networkLookupByName(virConnectPtr conn,
1806
 
                                         const char *name) {
1807
 
    struct network_driver *driver = conn->networkPrivateData;
1808
 
    virNetworkObjPtr network;
1809
 
    virNetworkPtr ret = NULL;
1810
 
 
1811
 
    networkDriverLock(driver);
1812
 
    network = virNetworkFindByName(&driver->networks, name);
1813
 
    networkDriverUnlock(driver);
1814
 
    if (!network) {
1815
 
        networkReportError(VIR_ERR_NO_NETWORK,
1816
 
                           _("no network with matching name '%s'"), name);
1817
 
        goto cleanup;
1818
 
    }
1819
 
 
1820
 
    ret = virGetNetwork(conn, network->def->name, network->def->uuid);
1821
 
 
1822
 
cleanup:
1823
 
    if (network)
1824
 
        virNetworkObjUnlock(network);
1825
 
    return ret;
1826
 
}
1827
 
 
1828
 
static virDrvOpenStatus networkOpenNetwork(virConnectPtr conn,
1829
 
                                           virConnectAuthPtr auth ATTRIBUTE_UNUSED,
1830
 
                                           int flags ATTRIBUTE_UNUSED) {
1831
 
    if (!driverState)
1832
 
        return VIR_DRV_OPEN_DECLINED;
1833
 
 
1834
 
    conn->networkPrivateData = driverState;
1835
 
    return VIR_DRV_OPEN_SUCCESS;
1836
 
}
1837
 
 
1838
 
static int networkCloseNetwork(virConnectPtr conn) {
1839
 
    conn->networkPrivateData = NULL;
1840
 
    return 0;
1841
 
}
1842
 
 
1843
 
static int networkNumNetworks(virConnectPtr conn) {
1844
 
    int nactive = 0, i;
1845
 
    struct network_driver *driver = conn->networkPrivateData;
1846
 
 
1847
 
    networkDriverLock(driver);
1848
 
    for (i = 0 ; i < driver->networks.count ; i++) {
1849
 
        virNetworkObjLock(driver->networks.objs[i]);
1850
 
        if (virNetworkObjIsActive(driver->networks.objs[i]))
1851
 
            nactive++;
1852
 
        virNetworkObjUnlock(driver->networks.objs[i]);
1853
 
    }
1854
 
    networkDriverUnlock(driver);
1855
 
 
1856
 
    return nactive;
1857
 
}
1858
 
 
1859
 
static int networkListNetworks(virConnectPtr conn, char **const names, int nnames) {
1860
 
    struct network_driver *driver = conn->networkPrivateData;
1861
 
    int got = 0, i;
1862
 
 
1863
 
    networkDriverLock(driver);
1864
 
    for (i = 0 ; i < driver->networks.count && got < nnames ; i++) {
1865
 
        virNetworkObjLock(driver->networks.objs[i]);
1866
 
        if (virNetworkObjIsActive(driver->networks.objs[i])) {
1867
 
            if (!(names[got] = strdup(driver->networks.objs[i]->def->name))) {
1868
 
                virNetworkObjUnlock(driver->networks.objs[i]);
1869
 
                virReportOOMError();
1870
 
                goto cleanup;
1871
 
            }
1872
 
            got++;
1873
 
        }
1874
 
        virNetworkObjUnlock(driver->networks.objs[i]);
1875
 
    }
1876
 
    networkDriverUnlock(driver);
1877
 
 
1878
 
    return got;
1879
 
 
1880
 
 cleanup:
1881
 
    networkDriverUnlock(driver);
1882
 
    for (i = 0 ; i < got ; i++)
1883
 
        VIR_FREE(names[i]);
1884
 
    return -1;
1885
 
}
1886
 
 
1887
 
static int networkNumDefinedNetworks(virConnectPtr conn) {
1888
 
    int ninactive = 0, i;
1889
 
    struct network_driver *driver = conn->networkPrivateData;
1890
 
 
1891
 
    networkDriverLock(driver);
1892
 
    for (i = 0 ; i < driver->networks.count ; i++) {
1893
 
        virNetworkObjLock(driver->networks.objs[i]);
1894
 
        if (!virNetworkObjIsActive(driver->networks.objs[i]))
1895
 
            ninactive++;
1896
 
        virNetworkObjUnlock(driver->networks.objs[i]);
1897
 
    }
1898
 
    networkDriverUnlock(driver);
1899
 
 
1900
 
    return ninactive;
1901
 
}
1902
 
 
1903
 
static int networkListDefinedNetworks(virConnectPtr conn, char **const names, int nnames) {
1904
 
    struct network_driver *driver = conn->networkPrivateData;
1905
 
    int got = 0, i;
1906
 
 
1907
 
    networkDriverLock(driver);
1908
 
    for (i = 0 ; i < driver->networks.count && got < nnames ; i++) {
1909
 
        virNetworkObjLock(driver->networks.objs[i]);
1910
 
        if (!virNetworkObjIsActive(driver->networks.objs[i])) {
1911
 
            if (!(names[got] = strdup(driver->networks.objs[i]->def->name))) {
1912
 
                virNetworkObjUnlock(driver->networks.objs[i]);
1913
 
                virReportOOMError();
1914
 
                goto cleanup;
1915
 
            }
1916
 
            got++;
1917
 
        }
1918
 
        virNetworkObjUnlock(driver->networks.objs[i]);
1919
 
    }
1920
 
    networkDriverUnlock(driver);
1921
 
    return got;
1922
 
 
1923
 
 cleanup:
1924
 
    networkDriverUnlock(driver);
1925
 
    for (i = 0 ; i < got ; i++)
1926
 
        VIR_FREE(names[i]);
1927
 
    return -1;
1928
 
}
1929
 
 
1930
 
 
1931
 
static int networkIsActive(virNetworkPtr net)
1932
 
{
1933
 
    struct network_driver *driver = net->conn->networkPrivateData;
1934
 
    virNetworkObjPtr obj;
1935
 
    int ret = -1;
1936
 
 
1937
 
    networkDriverLock(driver);
1938
 
    obj = virNetworkFindByUUID(&driver->networks, net->uuid);
1939
 
    networkDriverUnlock(driver);
1940
 
    if (!obj) {
1941
 
        networkReportError(VIR_ERR_NO_NETWORK, NULL);
1942
 
        goto cleanup;
1943
 
    }
1944
 
    ret = virNetworkObjIsActive(obj);
1945
 
 
1946
 
cleanup:
1947
 
    if (obj)
1948
 
        virNetworkObjUnlock(obj);
1949
 
    return ret;
1950
 
}
1951
 
 
1952
 
static int networkIsPersistent(virNetworkPtr net)
1953
 
{
1954
 
    struct network_driver *driver = net->conn->networkPrivateData;
1955
 
    virNetworkObjPtr obj;
1956
 
    int ret = -1;
1957
 
 
1958
 
    networkDriverLock(driver);
1959
 
    obj = virNetworkFindByUUID(&driver->networks, net->uuid);
1960
 
    networkDriverUnlock(driver);
1961
 
    if (!obj) {
1962
 
        networkReportError(VIR_ERR_NO_NETWORK, NULL);
1963
 
        goto cleanup;
1964
 
    }
1965
 
    ret = obj->persistent;
1966
 
 
1967
 
cleanup:
1968
 
    if (obj)
1969
 
        virNetworkObjUnlock(obj);
1970
 
    return ret;
1971
 
}
1972
 
 
1973
 
 
1974
 
static virNetworkPtr networkCreate(virConnectPtr conn, const char *xml) {
1975
 
    struct network_driver *driver = conn->networkPrivateData;
1976
 
    virNetworkDefPtr def;
1977
 
    virNetworkObjPtr network = NULL;
1978
 
    virNetworkPtr ret = NULL;
1979
 
 
1980
 
    networkDriverLock(driver);
1981
 
 
1982
 
    if (!(def = virNetworkDefParseString(xml)))
1983
 
        goto cleanup;
1984
 
 
1985
 
    if (virNetworkObjIsDuplicate(&driver->networks, def, 1) < 0)
1986
 
        goto cleanup;
1987
 
 
1988
 
    if (virNetworkSetBridgeName(&driver->networks, def, 1))
1989
 
        goto cleanup;
1990
 
 
1991
 
    if (!(network = virNetworkAssignDef(&driver->networks,
1992
 
                                        def)))
1993
 
        goto cleanup;
1994
 
    def = NULL;
1995
 
 
1996
 
    if (networkStartNetworkDaemon(driver, network) < 0) {
1997
 
        virNetworkRemoveInactive(&driver->networks,
1998
 
                                 network);
1999
 
        network = NULL;
2000
 
        goto cleanup;
2001
 
    }
2002
 
 
2003
 
    ret = virGetNetwork(conn, network->def->name, network->def->uuid);
2004
 
 
2005
 
cleanup:
2006
 
    virNetworkDefFree(def);
2007
 
    if (network)
2008
 
        virNetworkObjUnlock(network);
2009
 
    networkDriverUnlock(driver);
2010
 
    return ret;
2011
 
}
2012
 
 
2013
 
static virNetworkPtr networkDefine(virConnectPtr conn, const char *xml) {
2014
 
    struct network_driver *driver = conn->networkPrivateData;
2015
 
    virNetworkIpDefPtr ipdef, ipv4def = NULL;
2016
 
    virNetworkDefPtr def;
2017
 
    virNetworkObjPtr network = NULL;
2018
 
    virNetworkPtr ret = NULL;
2019
 
    int ii;
2020
 
 
2021
 
    networkDriverLock(driver);
2022
 
 
2023
 
    if (!(def = virNetworkDefParseString(xml)))
2024
 
        goto cleanup;
2025
 
 
2026
 
    if (virNetworkObjIsDuplicate(&driver->networks, def, 0) < 0)
2027
 
        goto cleanup;
2028
 
 
2029
 
    if (virNetworkSetBridgeName(&driver->networks, def, 1))
2030
 
        goto cleanup;
2031
 
 
2032
 
    if (!(network = virNetworkAssignDef(&driver->networks,
2033
 
                                        def)))
2034
 
        goto cleanup;
2035
 
    def = NULL;
2036
 
 
2037
 
    network->persistent = 1;
2038
 
 
2039
 
    if (virNetworkSaveConfig(driver->networkConfigDir,
2040
 
                             network->newDef ? network->newDef : network->def) < 0) {
2041
 
        virNetworkRemoveInactive(&driver->networks,
2042
 
                                 network);
2043
 
        network = NULL;
2044
 
        goto cleanup;
2045
 
    }
2046
 
 
2047
 
    /* We only support dhcp on one IPv4 address per defined network */
2048
 
    for (ii = 0;
2049
 
         (ipdef = virNetworkDefGetIpByIndex(network->def, AF_UNSPEC, ii));
2050
 
         ii++) {
2051
 
        if (VIR_SOCKET_IS_FAMILY(&ipdef->address, AF_INET)) {
2052
 
            if (ipdef->nranges || ipdef->nhosts) {
2053
 
                if (ipv4def) {
2054
 
                    networkReportError(VIR_ERR_CONFIG_UNSUPPORTED,
2055
 
                                       "%s", _("Multiple dhcp sections found. dhcp is supported only for a single IPv4 address on each network"));
2056
 
                    goto cleanup;
2057
 
                } else {
2058
 
                    ipv4def = ipdef;
2059
 
                }
2060
 
            }
2061
 
        }
2062
 
    }
2063
 
    if (ipv4def) {
2064
 
        dnsmasqContext *dctx = dnsmasqContextNew(network->def->name, DNSMASQ_STATE_DIR);
2065
 
        if (dctx == NULL)
2066
 
            goto cleanup;
2067
 
 
2068
 
        networkSaveDnsmasqHostsfile(ipv4def, dctx, true);
2069
 
        dnsmasqContextFree(dctx);
2070
 
    }
2071
 
 
2072
 
    ret = virGetNetwork(conn, network->def->name, network->def->uuid);
2073
 
 
2074
 
cleanup:
2075
 
    virNetworkDefFree(def);
2076
 
    if (network)
2077
 
        virNetworkObjUnlock(network);
2078
 
    networkDriverUnlock(driver);
2079
 
    return ret;
2080
 
}
2081
 
 
2082
 
static int networkUndefine(virNetworkPtr net) {
2083
 
    struct network_driver *driver = net->conn->networkPrivateData;
2084
 
    virNetworkObjPtr network;
2085
 
    virNetworkIpDefPtr ipdef;
2086
 
    bool dhcp_present = false, v6present = false;
2087
 
    int ret = -1, ii;
2088
 
 
2089
 
    networkDriverLock(driver);
2090
 
 
2091
 
    network = virNetworkFindByUUID(&driver->networks, net->uuid);
2092
 
    if (!network) {
2093
 
        networkReportError(VIR_ERR_NO_NETWORK,
2094
 
                           "%s", _("no network with matching uuid"));
2095
 
        goto cleanup;
2096
 
    }
2097
 
 
2098
 
    if (virNetworkObjIsActive(network)) {
2099
 
        networkReportError(VIR_ERR_OPERATION_INVALID,
2100
 
                           "%s", _("network is still active"));
2101
 
        goto cleanup;
2102
 
    }
2103
 
 
2104
 
    if (virNetworkDeleteConfig(driver->networkConfigDir,
2105
 
                               driver->networkAutostartDir,
2106
 
                               network) < 0)
2107
 
        goto cleanup;
2108
 
 
2109
 
    /* we only support dhcp on one IPv4 address per defined network */
2110
 
    for (ii = 0;
2111
 
         (ipdef = virNetworkDefGetIpByIndex(network->def, AF_UNSPEC, ii));
2112
 
         ii++) {
2113
 
        if (VIR_SOCKET_IS_FAMILY(&ipdef->address, AF_INET)) {
2114
 
            if (ipdef->nranges || ipdef->nhosts)
2115
 
                dhcp_present = true;
2116
 
        } else if (VIR_SOCKET_IS_FAMILY(&ipdef->address, AF_INET6)) {
2117
 
            v6present = true;
2118
 
        }
2119
 
    }
2120
 
 
2121
 
    if (dhcp_present) {
2122
 
        dnsmasqContext *dctx = dnsmasqContextNew(network->def->name, DNSMASQ_STATE_DIR);
2123
 
        if (dctx == NULL)
2124
 
            goto cleanup;
2125
 
 
2126
 
        dnsmasqDelete(dctx);
2127
 
        dnsmasqContextFree(dctx);
2128
 
    }
2129
 
 
2130
 
    if (v6present) {
2131
 
        char *configfile = networkRadvdConfigFileName(network->def->name);
2132
 
 
2133
 
        if (!configfile) {
2134
 
            virReportOOMError();
2135
 
            goto cleanup;
2136
 
        }
2137
 
        unlink(configfile);
2138
 
        VIR_FREE(configfile);
2139
 
 
2140
 
        char *radvdpidbase = networkRadvdPidfileBasename(network->def->name);
2141
 
 
2142
 
        if (!(radvdpidbase)) {
2143
 
            virReportOOMError();
2144
 
            goto cleanup;
2145
 
        }
2146
 
        virFileDeletePid(NETWORK_PID_DIR, radvdpidbase);
2147
 
        VIR_FREE(radvdpidbase);
2148
 
 
2149
 
    }
2150
 
 
2151
 
    virNetworkRemoveInactive(&driver->networks,
2152
 
                             network);
2153
 
    network = NULL;
2154
 
    ret = 0;
2155
 
 
2156
 
cleanup:
2157
 
    if (network)
2158
 
        virNetworkObjUnlock(network);
2159
 
    networkDriverUnlock(driver);
2160
 
    return ret;
2161
 
}
2162
 
 
2163
 
static int networkStart(virNetworkPtr net) {
2164
 
    struct network_driver *driver = net->conn->networkPrivateData;
2165
 
    virNetworkObjPtr network;
2166
 
    int ret = -1;
2167
 
 
2168
 
    networkDriverLock(driver);
2169
 
    network = virNetworkFindByUUID(&driver->networks, net->uuid);
2170
 
 
2171
 
    if (!network) {
2172
 
        networkReportError(VIR_ERR_NO_NETWORK,
2173
 
                           "%s", _("no network with matching uuid"));
2174
 
        goto cleanup;
2175
 
    }
2176
 
 
2177
 
    ret = networkStartNetworkDaemon(driver, network);
2178
 
 
2179
 
cleanup:
2180
 
    if (network)
2181
 
        virNetworkObjUnlock(network);
2182
 
    networkDriverUnlock(driver);
2183
 
    return ret;
2184
 
}
2185
 
 
2186
 
static int networkDestroy(virNetworkPtr net) {
2187
 
    struct network_driver *driver = net->conn->networkPrivateData;
2188
 
    virNetworkObjPtr network;
2189
 
    int ret = -1;
2190
 
 
2191
 
    networkDriverLock(driver);
2192
 
    network = virNetworkFindByUUID(&driver->networks, net->uuid);
2193
 
 
2194
 
    if (!network) {
2195
 
        networkReportError(VIR_ERR_NO_NETWORK,
2196
 
                           "%s", _("no network with matching uuid"));
2197
 
        goto cleanup;
2198
 
    }
2199
 
 
2200
 
    if (!virNetworkObjIsActive(network)) {
2201
 
        networkReportError(VIR_ERR_OPERATION_INVALID,
2202
 
                           "%s", _("network is not active"));
2203
 
        goto cleanup;
2204
 
    }
2205
 
 
2206
 
    ret = networkShutdownNetworkDaemon(driver, network);
2207
 
    if (!network->persistent) {
2208
 
        virNetworkRemoveInactive(&driver->networks,
2209
 
                                 network);
2210
 
        network = NULL;
2211
 
    }
2212
 
 
2213
 
cleanup:
2214
 
    if (network)
2215
 
        virNetworkObjUnlock(network);
2216
 
    networkDriverUnlock(driver);
2217
 
    return ret;
2218
 
}
2219
 
 
2220
 
static char *networkDumpXML(virNetworkPtr net, int flags ATTRIBUTE_UNUSED) {
2221
 
    struct network_driver *driver = net->conn->networkPrivateData;
2222
 
    virNetworkObjPtr network;
2223
 
    char *ret = NULL;
2224
 
 
2225
 
    networkDriverLock(driver);
2226
 
    network = virNetworkFindByUUID(&driver->networks, net->uuid);
2227
 
    networkDriverUnlock(driver);
2228
 
 
2229
 
    if (!network) {
2230
 
        networkReportError(VIR_ERR_NO_NETWORK,
2231
 
                           "%s", _("no network with matching uuid"));
2232
 
        goto cleanup;
2233
 
    }
2234
 
 
2235
 
    ret = virNetworkDefFormat(network->def);
2236
 
 
2237
 
cleanup:
2238
 
    if (network)
2239
 
        virNetworkObjUnlock(network);
2240
 
    return ret;
2241
 
}
2242
 
 
2243
 
static char *networkGetBridgeName(virNetworkPtr net) {
2244
 
    struct network_driver *driver = net->conn->networkPrivateData;
2245
 
    virNetworkObjPtr network;
2246
 
    char *bridge = NULL;
2247
 
 
2248
 
    networkDriverLock(driver);
2249
 
    network = virNetworkFindByUUID(&driver->networks, net->uuid);
2250
 
    networkDriverUnlock(driver);
2251
 
 
2252
 
    if (!network) {
2253
 
        networkReportError(VIR_ERR_NO_NETWORK,
2254
 
                           "%s", _("no network with matching id"));
2255
 
        goto cleanup;
2256
 
    }
2257
 
 
2258
 
    if (!(network->def->bridge)) {
2259
 
        networkReportError(VIR_ERR_INTERNAL_ERROR,
2260
 
                           _("network '%s' does not have a bridge name."),
2261
 
                           network->def->name);
2262
 
        goto cleanup;
2263
 
    }
2264
 
 
2265
 
    bridge = strdup(network->def->bridge);
2266
 
    if (!bridge)
2267
 
        virReportOOMError();
2268
 
 
2269
 
cleanup:
2270
 
    if (network)
2271
 
        virNetworkObjUnlock(network);
2272
 
    return bridge;
2273
 
}
2274
 
 
2275
 
static int networkGetAutostart(virNetworkPtr net,
2276
 
                             int *autostart) {
2277
 
    struct network_driver *driver = net->conn->networkPrivateData;
2278
 
    virNetworkObjPtr network;
2279
 
    int ret = -1;
2280
 
 
2281
 
    networkDriverLock(driver);
2282
 
    network = virNetworkFindByUUID(&driver->networks, net->uuid);
2283
 
    networkDriverUnlock(driver);
2284
 
    if (!network) {
2285
 
        networkReportError(VIR_ERR_NO_NETWORK,
2286
 
                           "%s", _("no network with matching uuid"));
2287
 
        goto cleanup;
2288
 
    }
2289
 
 
2290
 
    *autostart = network->autostart;
2291
 
    ret = 0;
2292
 
 
2293
 
cleanup:
2294
 
    if (network)
2295
 
        virNetworkObjUnlock(network);
2296
 
    return ret;
2297
 
}
2298
 
 
2299
 
static int networkSetAutostart(virNetworkPtr net,
2300
 
                               int autostart) {
2301
 
    struct network_driver *driver = net->conn->networkPrivateData;
2302
 
    virNetworkObjPtr network;
2303
 
    char *configFile = NULL, *autostartLink = NULL;
2304
 
    int ret = -1;
2305
 
 
2306
 
    networkDriverLock(driver);
2307
 
    network = virNetworkFindByUUID(&driver->networks, net->uuid);
2308
 
 
2309
 
    if (!network) {
2310
 
        networkReportError(VIR_ERR_NO_NETWORK,
2311
 
                           "%s", _("no network with matching uuid"));
2312
 
        goto cleanup;
2313
 
    }
2314
 
 
2315
 
    if (!network->persistent) {
2316
 
        networkReportError(VIR_ERR_OPERATION_INVALID,
2317
 
                           "%s", _("cannot set autostart for transient network"));
2318
 
        goto cleanup;
2319
 
    }
2320
 
 
2321
 
    autostart = (autostart != 0);
2322
 
 
2323
 
    if (network->autostart != autostart) {
2324
 
        if ((configFile = virNetworkConfigFile(driver->networkConfigDir, network->def->name)) == NULL)
2325
 
            goto cleanup;
2326
 
        if ((autostartLink = virNetworkConfigFile(driver->networkAutostartDir, network->def->name)) == NULL)
2327
 
            goto cleanup;
2328
 
 
2329
 
        if (autostart) {
2330
 
            if (virFileMakePath(driver->networkAutostartDir)) {
2331
 
                virReportSystemError(errno,
2332
 
                                     _("cannot create autostart directory '%s'"),
2333
 
                                     driver->networkAutostartDir);
2334
 
                goto cleanup;
2335
 
            }
2336
 
 
2337
 
            if (symlink(configFile, autostartLink) < 0) {
2338
 
                virReportSystemError(errno,
2339
 
                                     _("Failed to create symlink '%s' to '%s'"),
2340
 
                                     autostartLink, configFile);
2341
 
                goto cleanup;
2342
 
            }
2343
 
        } else {
2344
 
            if (unlink(autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) {
2345
 
                virReportSystemError(errno,
2346
 
                                     _("Failed to delete symlink '%s'"),
2347
 
                                     autostartLink);
2348
 
                goto cleanup;
2349
 
            }
2350
 
        }
2351
 
 
2352
 
        network->autostart = autostart;
2353
 
    }
2354
 
    ret = 0;
2355
 
 
2356
 
cleanup:
2357
 
    VIR_FREE(configFile);
2358
 
    VIR_FREE(autostartLink);
2359
 
    if (network)
2360
 
        virNetworkObjUnlock(network);
2361
 
    networkDriverUnlock(driver);
2362
 
    return ret;
2363
 
}
2364
 
 
2365
 
 
2366
 
static virNetworkDriver networkDriver = {
2367
 
    "Network",
2368
 
    networkOpenNetwork, /* open */
2369
 
    networkCloseNetwork, /* close */
2370
 
    networkNumNetworks, /* numOfNetworks */
2371
 
    networkListNetworks, /* listNetworks */
2372
 
    networkNumDefinedNetworks, /* numOfDefinedNetworks */
2373
 
    networkListDefinedNetworks, /* listDefinedNetworks */
2374
 
    networkLookupByUUID, /* networkLookupByUUID */
2375
 
    networkLookupByName, /* networkLookupByName */
2376
 
    networkCreate, /* networkCreateXML */
2377
 
    networkDefine, /* networkDefineXML */
2378
 
    networkUndefine, /* networkUndefine */
2379
 
    networkStart, /* networkCreate */
2380
 
    networkDestroy, /* networkDestroy */
2381
 
    networkDumpXML, /* networkDumpXML */
2382
 
    networkGetBridgeName, /* networkGetBridgeName */
2383
 
    networkGetAutostart, /* networkGetAutostart */
2384
 
    networkSetAutostart, /* networkSetAutostart */
2385
 
    networkIsActive,
2386
 
    networkIsPersistent,
2387
 
};
2388
 
 
2389
 
static virStateDriver networkStateDriver = {
2390
 
    "Network",
2391
 
    networkStartup,
2392
 
    networkShutdown,
2393
 
    networkReload,
2394
 
    networkActive,
2395
 
};
2396
 
 
2397
 
int networkRegister(void) {
2398
 
    virRegisterNetworkDriver(&networkDriver);
2399
 
    virRegisterStateDriver(&networkStateDriver);
2400
 
    return 0;
2401
 
}