bridge_driver_linux.c 23.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
/*
 * bridge_driver_linux.c: Linux implementation of bridge driver
 *
 * Copyright (C) 2006-2013 Red Hat, Inc.
 * Copyright (C) 2006 Daniel P. Berrange
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library.  If not, see
 * <http://www.gnu.org/licenses/>.
 */

#include <config.h>

#include "viralloc.h"
#include "virfile.h"
#include "viriptables.h"
#include "virstring.h"
28
#include "virlog.h"
29
#include "virfirewall.h"
30 31 32

#define VIR_FROM_THIS VIR_FROM_NONE

33 34
VIR_LOG_INIT("network.bridge_driver_linux");

35 36
#define PROC_NET_ROUTE "/proc/net/route"

37 38 39 40 41 42 43 44 45 46 47
int networkPreReloadFirewallRules(bool startup ATTRIBUTE_UNUSED)
{
    return 0;
}


void networkPostReloadFirewallRules(bool startup ATTRIBUTE_UNUSED)
{
}


48 49 50 51
/* XXX: This function can be a lot more exhaustive, there are certainly
 *      other scenarios where we can ruin host network connectivity.
 * XXX: Using a proper library is preferred over parsing /proc
 */
52
int networkCheckRouteCollision(virNetworkDefPtr def)
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
{
    int ret = 0, len;
    char *cur, *buf = NULL;
    /* allow for up to 100000 routes (each line is 128 bytes) */
    enum {MAX_ROUTE_SIZE = 128*100000};

    /* Read whole routing table into memory */
    if ((len = virFileReadAll(PROC_NET_ROUTE, MAX_ROUTE_SIZE, &buf)) < 0)
        goto out;

    /* Dropping the last character shouldn't hurt */
    if (len > 0)
        buf[len-1] = '\0';

    VIR_DEBUG("%s output:\n%s", PROC_NET_ROUTE, buf);

    if (!STRPREFIX(buf, "Iface"))
        goto out;

    /* First line is just headings, skip it */
    cur = strchr(buf, '\n');
    if (cur)
        cur++;

    while (cur) {
        char iface[17], dest[128], mask[128];
        unsigned int addr_val, mask_val;
80
        virNetworkIPDefPtr ipdef;
81
        virNetDevIPRoutePtr routedef;
82 83 84 85 86
        int num;
        size_t i;

        /* NUL-terminate the line, so sscanf doesn't go beyond a newline.  */
        char *nl = strchr(cur, '\n');
87
        if (nl)
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
            *nl++ = '\0';

        num = sscanf(cur, "%16s %127s %*s %*s %*s %*s %*s %127s",
                     iface, dest, mask);
        cur = nl;

        if (num != 3) {
            VIR_DEBUG("Failed to parse %s", PROC_NET_ROUTE);
            continue;
        }

        if (virStrToLong_ui(dest, NULL, 16, &addr_val) < 0) {
            VIR_DEBUG("Failed to convert network address %s to uint", dest);
            continue;
        }

        if (virStrToLong_ui(mask, NULL, 16, &mask_val) < 0) {
            VIR_DEBUG("Failed to convert network mask %s to uint", mask);
            continue;
        }

        addr_val &= mask_val;

        for (i = 0;
112
             (ipdef = virNetworkDefGetIPByIndex(def, AF_INET, i));
113 114 115 116 117
             i++) {

            unsigned int net_dest;
            virSocketAddr netmask;

118
            if (virNetworkIPDefNetmask(ipdef, &netmask) < 0) {
119
                VIR_WARN("Failed to get netmask of '%s'",
120
                         def->bridge);
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
                continue;
            }

            net_dest = (ipdef->address.data.inet4.sin_addr.s_addr &
                        netmask.data.inet4.sin_addr.s_addr);

            if ((net_dest == addr_val) &&
                (netmask.data.inet4.sin_addr.s_addr == mask_val)) {
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("Network is already in use by interface %s"),
                               iface);
                ret = -1;
                goto out;
            }
        }
136 137 138 139 140 141

        for (i = 0;
             (routedef = virNetworkDefGetRouteByIndex(def, AF_INET, i));
             i++) {

            virSocketAddr r_mask, r_addr;
142 143
            virSocketAddrPtr tmp_addr = virNetDevIPRouteGetAddress(routedef);
            int r_prefix = virNetDevIPRouteGetPrefix(routedef);
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163

            if (!tmp_addr ||
                virSocketAddrMaskByPrefix(tmp_addr, r_prefix, &r_addr) < 0 ||
                virSocketAddrPrefixToNetmask(r_prefix, &r_mask, AF_INET) < 0)
                continue;

            if ((r_addr.data.inet4.sin_addr.s_addr == addr_val) &&
                (r_mask.data.inet4.sin_addr.s_addr == mask_val)) {
                char *addr_str = virSocketAddrFormat(&r_addr);
                if (!addr_str)
                    virResetLastError();
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("Route address '%s' conflicts "
                                 "with IP address for '%s'"),
                               NULLSTR(addr_str), iface);
                VIR_FREE(addr_str);
                ret = -1;
                goto out;
            }
        }
164 165
    }

166
 out:
167 168 169 170
    VIR_FREE(buf);
    return ret;
}

171 172 173
static const char networkLocalMulticast[] = "224.0.0.0/24";
static const char networkLocalBroadcast[] = "255.255.255.255/32";

174
static int
175
networkAddMasqueradingFirewallRules(virFirewallPtr fw,
176
                                    virNetworkDefPtr def,
177
                                    virNetworkIPDefPtr ipdef)
178
{
179
    int prefix = virNetworkIPDefPrefix(ipdef);
180
    const char *forwardIf = virNetworkDefForwardIf(def, 0);
181 182 183 184

    if (prefix < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Invalid prefix or netmask for '%s'"),
185
                       def->bridge);
186
        return -1;
187 188 189
    }

    /* allow forwarding packets from the bridge interface */
190 191
    if (iptablesAddForwardAllowOut(fw,
                                   &ipdef->address,
192
                                   prefix,
193
                                   def->bridge,
194 195
                                   forwardIf) < 0)
        return -1;
196 197 198 199

    /* allow forwarding packets to the bridge interface if they are
     * part of an existing connection
     */
200 201
    if (iptablesAddForwardAllowRelatedIn(fw,
                                         &ipdef->address,
202
                                         prefix,
203
                                         def->bridge,
204 205
                                         forwardIf) < 0)
        return -1;
206 207 208 209

    /*
     * Enable masquerading.
     *
210 211 212 213 214 215 216
     * We need to end up with 5 rules in the table in this order
     *
     *  1. do not masquerade packets targeting 224.0.0.0/24
     *  2. do not masquerade packets targeting 255.255.255.255/32
     *  3. masquerade protocol=tcp with sport mapping restriction
     *  4. masquerade protocol=udp with sport mapping restriction
     *  5. generic, masquerade any protocol
217
     *
218 219 220 221 222 223
     * 224.0.0.0/24 is the local network multicast range. Packets are not
     * forwarded outside.
     *
     * 255.255.255.255/32 is the broadcast address of any local network. Again,
     * such packets are never forwarded, but strict DHCP clients don't accept
     * DHCP replies with changed source ports.
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
     *
     * The sport mappings are required, because default IPtables
     * MASQUERADE maintain port numbers unchanged where possible.
     *
     * NFS can be configured to only "trust" port numbers < 1023.
     *
     * Guests using NAT thus need to be prevented from having port
     * numbers < 1023, otherwise they can bypass the NFS "security"
     * check on the source port number.
     *
     * Since we use '--insert' to add rules to the header of the
     * chain, we actually need to add them in the reverse of the
     * order just mentioned !
     */

    /* First the generic masquerade rule for other protocols */
240 241
    if (iptablesAddForwardMasquerade(fw,
                                     &ipdef->address,
242 243
                                     prefix,
                                     forwardIf,
244 245
                                     &def->forward.addr,
                                     &def->forward.port,
246 247
                                     NULL) < 0)
        return -1;
248 249

    /* UDP with a source port restriction */
250 251
    if (iptablesAddForwardMasquerade(fw,
                                     &ipdef->address,
252 253
                                     prefix,
                                     forwardIf,
254 255
                                     &def->forward.addr,
                                     &def->forward.port,
256 257
                                     "udp") < 0)
        return -1;
258 259

    /* TCP with a source port restriction */
260 261
    if (iptablesAddForwardMasquerade(fw,
                                     &ipdef->address,
262 263
                                     prefix,
                                     forwardIf,
264 265
                                     &def->forward.addr,
                                     &def->forward.port,
266 267
                                     "tcp") < 0)
        return -1;
268

269
    /* exempt local network broadcast address as destination */
270 271
    if (iptablesAddDontMasquerade(fw,
                                  &ipdef->address,
272 273
                                  prefix,
                                  forwardIf,
274 275
                                  networkLocalBroadcast) < 0)
        return -1;
276 277

    /* exempt local multicast range as destination */
278 279
    if (iptablesAddDontMasquerade(fw,
                                  &ipdef->address,
280 281
                                  prefix,
                                  forwardIf,
282 283
                                  networkLocalMulticast) < 0)
        return -1;
284

285 286 287
    return 0;
}

288 289
static int
networkRemoveMasqueradingFirewallRules(virFirewallPtr fw,
290
                                       virNetworkDefPtr def,
291
                                       virNetworkIPDefPtr ipdef)
292
{
293
    int prefix = virNetworkIPDefPrefix(ipdef);
294
    const char *forwardIf = virNetworkDefForwardIf(def, 0);
295

296 297 298 299 300
    if (prefix < 0)
        return 0;

    if (iptablesRemoveDontMasquerade(fw,
                                     &ipdef->address,
301 302
                                     prefix,
                                     forwardIf,
303 304 305 306 307
                                     networkLocalMulticast) < 0)
        return -1;

    if (iptablesRemoveDontMasquerade(fw,
                                     &ipdef->address,
308 309
                                     prefix,
                                     forwardIf,
310 311 312 313 314
                                     networkLocalBroadcast) < 0)
        return -1;

    if (iptablesRemoveForwardMasquerade(fw,
                                        &ipdef->address,
315 316
                                        prefix,
                                        forwardIf,
317 318
                                        &def->forward.addr,
                                        &def->forward.port,
319 320 321 322 323
                                        "tcp") < 0)
        return -1;

    if (iptablesRemoveForwardMasquerade(fw,
                                        &ipdef->address,
324 325
                                        prefix,
                                        forwardIf,
326 327
                                        &def->forward.addr,
                                        &def->forward.port,
328 329 330 331 332
                                        "udp") < 0)
        return -1;

    if (iptablesRemoveForwardMasquerade(fw,
                                        &ipdef->address,
333 334
                                        prefix,
                                        forwardIf,
335 336
                                        &def->forward.addr,
                                        &def->forward.port,
337 338
                                        NULL) < 0)
        return -1;
339

340 341
    if (iptablesRemoveForwardAllowRelatedIn(fw,
                                            &ipdef->address,
342
                                            prefix,
343
                                            def->bridge,
344 345 346 347 348
                                            forwardIf) < 0)
        return -1;

    if (iptablesRemoveForwardAllowOut(fw,
                                      &ipdef->address,
349
                                      prefix,
350
                                      def->bridge,
351 352 353 354
                                      forwardIf) < 0)
        return -1;

    return 0;
355 356
}

357

358
static int
359
networkAddRoutingFirewallRules(virFirewallPtr fw,
360
                               virNetworkDefPtr def,
361
                               virNetworkIPDefPtr ipdef)
362
{
363
    int prefix = virNetworkIPDefPrefix(ipdef);
364
    const char *forwardIf = virNetworkDefForwardIf(def, 0);
365 366 367 368

    if (prefix < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Invalid prefix or netmask for '%s'"),
369
                       def->bridge);
370
        return -1;
371 372 373
    }

    /* allow routing packets from the bridge interface */
374 375
    if (iptablesAddForwardAllowOut(fw,
                                   &ipdef->address,
376
                                   prefix,
377
                                   def->bridge,
378 379
                                   forwardIf) < 0)
        return -1;
380 381

    /* allow routing packets to the bridge interface */
382 383
    if (iptablesAddForwardAllowIn(fw,
                                  &ipdef->address,
384
                                  prefix,
385
                                  def->bridge,
386 387
                                  forwardIf) < 0)
        return -1;
388 389 390 391

    return 0;
}

392

393 394
static int
networkRemoveRoutingFirewallRules(virFirewallPtr fw,
395
                                  virNetworkDefPtr def,
396
                                  virNetworkIPDefPtr ipdef)
397
{
398
    int prefix = virNetworkIPDefPrefix(ipdef);
399
    const char *forwardIf = virNetworkDefForwardIf(def, 0);
400

401 402 403 404 405
    if (prefix < 0)
        return 0;

    if (iptablesRemoveForwardAllowIn(fw,
                                     &ipdef->address,
406
                                     prefix,
407
                                     def->bridge,
408 409
                                     forwardIf) < 0)
        return -1;
410

411 412
    if (iptablesRemoveForwardAllowOut(fw,
                                      &ipdef->address,
413
                                      prefix,
414
                                      def->bridge,
415 416 417 418 419 420 421 422 423
                                      forwardIf) < 0)
        return -1;

    return 0;
}


static void
networkAddGeneralIPv4FirewallRules(virFirewallPtr fw,
424
                                   virNetworkDefPtr def)
425 426
{
    size_t i;
427
    virNetworkIPDefPtr ipv4def;
428 429 430 431

    /* First look for first IPv4 address that has dhcp or tftpboot defined. */
    /* We support dhcp config on 1 IPv4 interface only. */
    for (i = 0;
432
         (ipv4def = virNetworkDefGetIPByIndex(def, AF_INET, i));
433 434 435 436 437 438
         i++) {
        if (ipv4def->nranges || ipv4def->nhosts || ipv4def->tftproot)
            break;
    }

    /* allow DHCP requests through to dnsmasq */
439 440 441
    iptablesAddTcpInput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 67);
    iptablesAddUdpInput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 67);
    iptablesAddUdpOutput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 68);
442 443

    /* allow DNS requests through to dnsmasq */
444 445
    iptablesAddTcpInput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 53);
    iptablesAddUdpInput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 53);
446 447 448

    /* allow TFTP requests through to dnsmasq if necessary */
    if (ipv4def && ipv4def->tftproot)
449
        iptablesAddUdpInput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 69);
450 451

    /* Catch all rules to block forwarding to/from bridges */
452 453
    iptablesAddForwardRejectOut(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge);
    iptablesAddForwardRejectIn(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge);
454 455

    /* Allow traffic between guests on the same bridge */
456
    iptablesAddForwardAllowCross(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge);
457 458 459 460
}

static void
networkRemoveGeneralIPv4FirewallRules(virFirewallPtr fw,
461
                                      virNetworkDefPtr def)
462 463
{
    size_t i;
464
    virNetworkIPDefPtr ipv4def;
465 466

    for (i = 0;
467
         (ipv4def = virNetworkDefGetIPByIndex(def, AF_INET, i));
468 469 470
         i++) {
        if (ipv4def->nranges || ipv4def->nhosts || ipv4def->tftproot)
            break;
471
    }
472

473 474 475
    iptablesRemoveForwardAllowCross(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge);
    iptablesRemoveForwardRejectIn(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge);
    iptablesRemoveForwardRejectOut(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge);
476 477

    if (ipv4def && ipv4def->tftproot)
478
        iptablesRemoveUdpInput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 69);
479

480 481
    iptablesRemoveUdpInput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 53);
    iptablesRemoveTcpInput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 53);
482

483 484 485
    iptablesRemoveUdpOutput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 68);
    iptablesRemoveUdpInput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 67);
    iptablesRemoveTcpInput(fw, VIR_FIREWALL_LAYER_IPV4, def->bridge, 67);
486 487
}

488

489 490
/* Add all once/network rules required for IPv6.
 * If no IPv6 addresses are defined and <network ipv6='yes'> is
M
Martin Kletzander 已提交
491
 * specified, then allow IPv6 communications between virtual systems.
492 493
 * If any IPv6 addresses are defined, then add the rules for regular operation.
 */
494 495
static void
networkAddGeneralIPv6FirewallRules(virFirewallPtr fw,
496
                                   virNetworkDefPtr def)
497
{
498
    if (!virNetworkDefGetIPByIndex(def, AF_INET6, 0) &&
499
        !def->ipv6nogw) {
500
        return;
501 502 503
    }

    /* Catch all rules to block forwarding to/from bridges */
504 505
    iptablesAddForwardRejectOut(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge);
    iptablesAddForwardRejectIn(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge);
506 507

    /* Allow traffic between guests on the same bridge */
508
    iptablesAddForwardAllowCross(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge);
509

510
    if (virNetworkDefGetIPByIndex(def, AF_INET6, 0)) {
511
        /* allow DNS over IPv6 */
512 513 514
        iptablesAddTcpInput(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge, 53);
        iptablesAddUdpInput(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge, 53);
        iptablesAddUdpInput(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge, 547);
515 516 517 518
    }
}

static void
519
networkRemoveGeneralIPv6FirewallRules(virFirewallPtr fw,
520
                                      virNetworkDefPtr def)
521
{
522
    if (!virNetworkDefGetIPByIndex(def, AF_INET6, 0) &&
523
        !def->ipv6nogw) {
524 525
        return;
    }
526

527
    if (virNetworkDefGetIPByIndex(def, AF_INET6, 0)) {
528 529 530
        iptablesRemoveUdpInput(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge, 547);
        iptablesRemoveUdpInput(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge, 53);
        iptablesRemoveTcpInput(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge, 53);
531 532 533
    }

    /* the following rules are there if no IPv6 address has been defined
534
     * but def->ipv6nogw == true
535
     */
536 537 538
    iptablesRemoveForwardAllowCross(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge);
    iptablesRemoveForwardRejectIn(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge);
    iptablesRemoveForwardRejectOut(fw, VIR_FIREWALL_LAYER_IPV6, def->bridge);
539 540
}

541

542 543
static void
networkAddGeneralFirewallRules(virFirewallPtr fw,
544
                               virNetworkDefPtr def)
545
{
546 547
    networkAddGeneralIPv4FirewallRules(fw, def);
    networkAddGeneralIPv6FirewallRules(fw, def);
548 549 550 551 552
}


static void
networkRemoveGeneralFirewallRules(virFirewallPtr fw,
553
                                  virNetworkDefPtr def)
554
{
555 556
    networkRemoveGeneralIPv4FirewallRules(fw, def);
    networkRemoveGeneralIPv6FirewallRules(fw, def);
557 558 559 560
}

static void
networkAddChecksumFirewallRules(virFirewallPtr fw,
561
                                virNetworkDefPtr def)
562 563
{
    size_t i;
564
    virNetworkIPDefPtr ipv4def;
565 566 567 568

    /* First look for first IPv4 address that has dhcp or tftpboot defined. */
    /* We support dhcp config on 1 IPv4 interface only. */
    for (i = 0;
569
         (ipv4def = virNetworkDefGetIPByIndex(def, AF_INET, i));
570
         i++) {
571
        if (ipv4def->nranges || ipv4def->nhosts)
572 573 574 575 576 577 578 579
            break;
    }

    /* If we are doing local DHCP service on this network, attempt to
     * add a rule that will fixup the checksum of DHCP response
     * packets back to the guests (but report failure without
     * aborting, since not all iptables implementations support it).
     */
580
    if (ipv4def)
581
        iptablesAddOutputFixUdpChecksum(fw, def->bridge, 68);
582 583
}

584 585

static void
586
networkRemoveChecksumFirewallRules(virFirewallPtr fw,
587
                                   virNetworkDefPtr def)
588 589
{
    size_t i;
590
    virNetworkIPDefPtr ipv4def;
591

592 593
    /* First look for first IPv4 address that has dhcp or tftpboot defined. */
    /* We support dhcp config on 1 IPv4 interface only. */
594
    for (i = 0;
595
         (ipv4def = virNetworkDefGetIPByIndex(def, AF_INET, i));
596
         i++) {
597
        if (ipv4def->nranges || ipv4def->nhosts)
598 599 600
            break;
    }

601
    if (ipv4def)
602
        iptablesRemoveOutputFixUdpChecksum(fw, def->bridge, 68);
603 604
}

605 606

static int
607
networkAddIPSpecificFirewallRules(virFirewallPtr fw,
608
                                  virNetworkDefPtr def,
609
                                  virNetworkIPDefPtr ipdef)
610 611 612 613 614
{
    /* NB: in the case of IPv6, routing rules are added when the
     * forward mode is NAT. This is because IPv6 has no NAT.
     */

615
    if (def->forward.type == VIR_NETWORK_FORWARD_NAT) {
616
        if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET))
617
            return networkAddMasqueradingFirewallRules(fw, def, ipdef);
618
        else if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET6))
619 620 621
            return networkAddRoutingFirewallRules(fw, def, ipdef);
    } else if (def->forward.type == VIR_NETWORK_FORWARD_ROUTE) {
        return networkAddRoutingFirewallRules(fw, def, ipdef);
622 623 624 625
    }
    return 0;
}

626

627
static int
628
networkRemoveIPSpecificFirewallRules(virFirewallPtr fw,
629
                                     virNetworkDefPtr def,
630
                                     virNetworkIPDefPtr ipdef)
631
{
632
    if (def->forward.type == VIR_NETWORK_FORWARD_NAT) {
633
        if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET))
634
            return networkRemoveMasqueradingFirewallRules(fw, def, ipdef);
635
        else if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET6))
636 637 638
            return networkRemoveRoutingFirewallRules(fw, def, ipdef);
    } else if (def->forward.type == VIR_NETWORK_FORWARD_ROUTE) {
        return networkRemoveRoutingFirewallRules(fw, def, ipdef);
639
    }
640
    return 0;
641 642
}

643

644
/* Add all rules for all ip addresses (and general rules) on a network */
645
int networkAddFirewallRules(virNetworkDefPtr def)
646
{
647
    size_t i;
648
    virNetworkIPDefPtr ipdef;
649 650
    virFirewallPtr fw = NULL;
    int ret = -1;
651

652 653 654 655
    fw = virFirewallNew();

    virFirewallStartTransaction(fw, 0);

656
    networkAddGeneralFirewallRules(fw, def);
657 658

    for (i = 0;
659
         (ipdef = virNetworkDefGetIPByIndex(def, AF_UNSPEC, i));
660
         i++) {
661
        if (networkAddIPSpecificFirewallRules(fw, def, ipdef) < 0)
662
            goto cleanup;
663 664
    }

665
    virFirewallStartRollback(fw, 0);
666

667
    for (i = 0;
668
         (ipdef = virNetworkDefGetIPByIndex(def, AF_UNSPEC, i));
669
         i++) {
670
        if (networkRemoveIPSpecificFirewallRules(fw, def, ipdef) < 0)
671
            goto cleanup;
672
    }
673
    networkRemoveGeneralFirewallRules(fw, def);
674 675

    virFirewallStartTransaction(fw, VIR_FIREWALL_TRANSACTION_IGNORE_ERRORS);
676
    networkAddChecksumFirewallRules(fw, def);
677 678 679

    if (virFirewallApply(fw) < 0)
        goto cleanup;
680

681 682 683 684
    ret = 0;
 cleanup:
    virFirewallFree(fw);
    return ret;
685 686 687
}

/* Remove all rules for all ip addresses (and general rules) on a network */
688
void networkRemoveFirewallRules(virNetworkDefPtr def)
689 690
{
    size_t i;
691
    virNetworkIPDefPtr ipdef;
692 693 694 695 696
    virFirewallPtr fw = NULL;

    fw = virFirewallNew();

    virFirewallStartTransaction(fw, VIR_FIREWALL_TRANSACTION_IGNORE_ERRORS);
697
    networkRemoveChecksumFirewallRules(fw, def);
698 699

    virFirewallStartTransaction(fw, VIR_FIREWALL_TRANSACTION_IGNORE_ERRORS);
700 701

    for (i = 0;
702
         (ipdef = virNetworkDefGetIPByIndex(def, AF_UNSPEC, i));
703
         i++) {
704
        if (networkRemoveIPSpecificFirewallRules(fw, def, ipdef) < 0)
705
            goto cleanup;
706
    }
707
    networkRemoveGeneralFirewallRules(fw, def);
708 709 710 711 712

    virFirewallApply(fw);

 cleanup:
    virFirewallFree(fw);
713
}