[libvirt] [PATCH 12/28] Rename iptables.{c, h} to viriptables.{c, h}

Daniel P. Berrange berrange at redhat.com
Mon Dec 17 14:57:45 UTC 2012


From: "Daniel P. Berrange" <berrange at redhat.com>

---
 po/POTFILES.in              |   2 +-
 src/Makefile.am             |   2 +-
 src/network/bridge_driver.c |   2 +-
 src/util/iptables.c         | 970 --------------------------------------------
 src/util/iptables.h         | 121 ------
 src/util/viriptables.c      | 970 ++++++++++++++++++++++++++++++++++++++++++++
 src/util/viriptables.h      | 121 ++++++
 7 files changed, 1094 insertions(+), 1094 deletions(-)
 delete mode 100644 src/util/iptables.c
 delete mode 100644 src/util/iptables.h
 create mode 100644 src/util/viriptables.c
 create mode 100644 src/util/viriptables.h

diff --git a/po/POTFILES.in b/po/POTFILES.in
index 3f3362c..f55a1b1 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -138,7 +138,6 @@ src/test/test_driver.c
 src/uml/uml_conf.c
 src/uml/uml_driver.c
 src/util/iohelper.c
-src/util/iptables.c
 src/util/json.c
 src/util/pci.c
 src/util/processinfo.c
@@ -160,6 +159,7 @@ src/util/virfile.c
 src/util/virhash.c
 src/util/virhooks.c
 src/util/virinitctl.c
+src/util/viriptables.c
 src/util/virkeyfile.c
 src/util/virlockspace.c
 src/util/virnetdev.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 4f89bdc..45e6169 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -53,7 +53,6 @@ augeastest_DATA =
 # These files are not related to driver APIs. Simply generic
 # helper APIs for various purposes
 UTIL_SOURCES =							\
-		util/iptables.c util/iptables.h			\
 		util/json.c util/json.h				\
 		util/logging.c util/logging.h			\
 		util/memory.c util/memory.h			\
@@ -84,6 +83,7 @@ UTIL_SOURCES =							\
 		util/virfile.c util/virfile.h			\
 		util/virhooks.c util/virhooks.h			\
 		util/virnodesuspend.c util/virnodesuspend.h	\
+		util/viriptables.c util/viriptables.h		\
 		util/virobject.c util/virobject.h		\
 		util/virpidfile.c util/virpidfile.h		\
 		util/virprocess.c util/virprocess.h		\
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 1110208..bc37bde 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -56,7 +56,7 @@
 #include "vircommand.h"
 #include "memory.h"
 #include "uuid.h"
-#include "iptables.h"
+#include "viriptables.h"
 #include "logging.h"
 #include "virdnsmasq.h"
 #include "configmake.h"
diff --git a/src/util/iptables.c b/src/util/iptables.c
deleted file mode 100644
index 25253ff..0000000
--- a/src/util/iptables.c
+++ /dev/null
@@ -1,970 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Red Hat, Inc.
- *
- * 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/>.
- *
- * Authors:
- *     Mark McLoughlin <markmc at redhat.com>
- */
-
-#include <config.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <errno.h>
-#include <limits.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
-
-#ifdef HAVE_PATHS_H
-# include <paths.h>
-#endif
-
-#include "internal.h"
-#include "iptables.h"
-#include "vircommand.h"
-#include "memory.h"
-#include "virterror_internal.h"
-#include "logging.h"
-#include "threads.h"
-
-#if HAVE_FIREWALLD
-static char *firewall_cmd_path = NULL;
-
-static int
-virIpTablesOnceInit(void)
-{
-    firewall_cmd_path = virFindFileInPath("firewall-cmd");
-    if (!firewall_cmd_path) {
-        VIR_INFO("firewall-cmd not found on system. "
-                 "firewalld support disabled for iptables.");
-    } else {
-        virCommandPtr cmd = virCommandNew(firewall_cmd_path);
-        int status;
-
-        virCommandAddArgList(cmd, "--state", NULL);
-        if (virCommandRun(cmd, &status) < 0 || status != 0) {
-            VIR_INFO("firewall-cmd found but disabled for iptables");
-            VIR_FREE(firewall_cmd_path);
-            firewall_cmd_path = NULL;
-        } else {
-            VIR_INFO("using firewalld for iptables commands");
-        }
-        virCommandFree(cmd);
-    }
-    return 0;
-}
-
-VIR_ONCE_GLOBAL_INIT(virIpTables)
-
-#endif
-
-#define VIR_FROM_THIS VIR_FROM_NONE
-
-enum {
-    ADD = 0,
-    REMOVE
-};
-
-typedef struct
-{
-    char  *table;
-    char  *chain;
-} iptRules;
-
-struct _iptablesContext
-{
-    iptRules *input_filter;
-    iptRules *forward_filter;
-    iptRules *nat_postrouting;
-    iptRules *mangle_postrouting;
-};
-
-static void
-iptRulesFree(iptRules *rules)
-{
-    VIR_FREE(rules->table);
-    VIR_FREE(rules->chain);
-    VIR_FREE(rules);
-}
-
-static iptRules *
-iptRulesNew(const char *table,
-            const char *chain)
-{
-    iptRules *rules;
-
-    if (VIR_ALLOC(rules) < 0)
-        return NULL;
-
-    if (!(rules->table = strdup(table)))
-        goto error;
-
-    if (!(rules->chain = strdup(chain)))
-        goto error;
-
-    return rules;
-
- error:
-    iptRulesFree(rules);
-    return NULL;
-}
-
-static int ATTRIBUTE_SENTINEL
-iptablesAddRemoveRule(iptRules *rules, int family, int action,
-                      const char *arg, ...)
-{
-    va_list args;
-    int ret;
-    virCommandPtr cmd = NULL;
-    const char *s;
-
-#if HAVE_FIREWALLD
-    virIpTablesInitialize();
-    if (firewall_cmd_path) {
-        cmd = virCommandNew(firewall_cmd_path);
-        virCommandAddArgList(cmd, "--direct", "--passthrough",
-                             (family == AF_INET6) ? "ipv6" : "ipv4", NULL);
-    }
-#endif
-
-    if (cmd == NULL) {
-        cmd = virCommandNew((family == AF_INET6)
-                        ? IP6TABLES_PATH : IPTABLES_PATH);
-    }
-
-    virCommandAddArgList(cmd, "--table", rules->table,
-                         action == ADD ? "--insert" : "--delete",
-                         rules->chain, arg, NULL);
-
-    va_start(args, arg);
-    while ((s = va_arg(args, const char *)))
-        virCommandAddArg(cmd, s);
-    va_end(args);
-
-    ret = virCommandRun(cmd, NULL);
-    virCommandFree(cmd);
-    return ret;
-}
-
-/**
- * iptablesContextNew:
- *
- * Create a new IPtable context
- *
- * Returns a pointer to the new structure or NULL in case of error
- */
-iptablesContext *
-iptablesContextNew(void)
-{
-    iptablesContext *ctx;
-
-    if (VIR_ALLOC(ctx) < 0)
-        return NULL;
-
-    if (!(ctx->input_filter = iptRulesNew("filter", "INPUT")))
-        goto error;
-
-    if (!(ctx->forward_filter = iptRulesNew("filter", "FORWARD")))
-        goto error;
-
-    if (!(ctx->nat_postrouting = iptRulesNew("nat", "POSTROUTING")))
-        goto error;
-
-    if (!(ctx->mangle_postrouting = iptRulesNew("mangle", "POSTROUTING")))
-        goto error;
-
-    return ctx;
-
- error:
-    iptablesContextFree(ctx);
-    return NULL;
-}
-
-/**
- * iptablesContextFree:
- * @ctx: pointer to the IP table context
- *
- * Free the resources associated with an IP table context
- */
-void
-iptablesContextFree(iptablesContext *ctx)
-{
-    if (ctx->input_filter)
-        iptRulesFree(ctx->input_filter);
-    if (ctx->forward_filter)
-        iptRulesFree(ctx->forward_filter);
-    if (ctx->nat_postrouting)
-        iptRulesFree(ctx->nat_postrouting);
-    if (ctx->mangle_postrouting)
-        iptRulesFree(ctx->mangle_postrouting);
-    VIR_FREE(ctx);
-}
-
-static int
-iptablesInput(iptablesContext *ctx,
-              int family,
-              const char *iface,
-              int port,
-              int action,
-              int tcp)
-{
-    char portstr[32];
-
-    snprintf(portstr, sizeof(portstr), "%d", port);
-    portstr[sizeof(portstr) - 1] = '\0';
-
-    return iptablesAddRemoveRule(ctx->input_filter,
-                                 family,
-                                 action,
-                                 "--in-interface", iface,
-                                 "--protocol", tcp ? "tcp" : "udp",
-                                 "--destination-port", portstr,
-                                 "--jump", "ACCEPT",
-                                 NULL);
-}
-
-/**
- * iptablesAddTcpInput:
- * @ctx: pointer to the IP table context
- * @iface: the interface name
- * @port: the TCP port to add
- *
- * Add an input to the IP table allowing access to the given @port on
- * the given @iface interface for TCP packets
- *
- * Returns 0 in case of success or an error code in case of error
- */
-
-int
-iptablesAddTcpInput(iptablesContext *ctx,
-                    int family,
-                    const char *iface,
-                    int port)
-{
-    return iptablesInput(ctx, family, iface, port, ADD, 1);
-}
-
-/**
- * iptablesRemoveTcpInput:
- * @ctx: pointer to the IP table context
- * @iface: the interface name
- * @port: the TCP port to remove
- *
- * Removes an input from the IP table, hence forbidding access to the given
- * @port on the given @iface interface for TCP packets
- *
- * Returns 0 in case of success or an error code in case of error
- */
-int
-iptablesRemoveTcpInput(iptablesContext *ctx,
-                       int family,
-                       const char *iface,
-                       int port)
-{
-    return iptablesInput(ctx, family, iface, port, REMOVE, 1);
-}
-
-/**
- * iptablesAddUdpInput:
- * @ctx: pointer to the IP table context
- * @iface: the interface name
- * @port: the UDP port to add
- *
- * Add an input to the IP table allowing access to the given @port on
- * the given @iface interface for UDP packets
- *
- * Returns 0 in case of success or an error code in case of error
- */
-
-int
-iptablesAddUdpInput(iptablesContext *ctx,
-                    int family,
-                    const char *iface,
-                    int port)
-{
-    return iptablesInput(ctx, family, iface, port, ADD, 0);
-}
-
-/**
- * iptablesRemoveUdpInput:
- * @ctx: pointer to the IP table context
- * @iface: the interface name
- * @port: the UDP port to remove
- *
- * Removes an input from the IP table, hence forbidding access to the given
- * @port on the given @iface interface for UDP packets
- *
- * Returns 0 in case of success or an error code in case of error
- */
-int
-iptablesRemoveUdpInput(iptablesContext *ctx,
-                       int family,
-                       const char *iface,
-                       int port)
-{
-    return iptablesInput(ctx, family, iface, port, REMOVE, 0);
-}
-
-
-static char *iptablesFormatNetwork(virSocketAddr *netaddr,
-                                   unsigned int prefix)
-{
-    virSocketAddr network;
-    char *netstr;
-    char *ret;
-
-    if (!(VIR_SOCKET_ADDR_IS_FAMILY(netaddr, AF_INET) ||
-          VIR_SOCKET_ADDR_IS_FAMILY(netaddr, AF_INET6))) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("Only IPv4 or IPv6 addresses can be used with iptables"));
-        return NULL;
-    }
-
-    if (virSocketAddrMaskByPrefix(netaddr, prefix, &network) < 0) {
-        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                       _("Failure to mask address"));
-        return NULL;
-    }
-
-    netstr = virSocketAddrFormat(&network);
-
-    if (!netstr)
-        return NULL;
-
-    if (virAsprintf(&ret, "%s/%d", netstr, prefix) < 0)
-        virReportOOMError();
-
-    VIR_FREE(netstr);
-    return ret;
-}
-
-
-/* Allow all traffic coming from the bridge, with a valid network address
- * to proceed to WAN
- */
-static int
-iptablesForwardAllowOut(iptablesContext *ctx,
-                        virSocketAddr *netaddr,
-                        unsigned int prefix,
-                        const char *iface,
-                        const char *physdev,
-                        int action)
-{
-    int ret;
-    char *networkstr;
-
-    if (!(networkstr = iptablesFormatNetwork(netaddr, prefix)))
-        return -1;
-
-    if (physdev && physdev[0]) {
-        ret = iptablesAddRemoveRule(ctx->forward_filter,
-                                    VIR_SOCKET_ADDR_FAMILY(netaddr),
-                                    action,
-                                    "--source", networkstr,
-                                    "--in-interface", iface,
-                                    "--out-interface", physdev,
-                                    "--jump", "ACCEPT",
-                                    NULL);
-    } else {
-        ret = iptablesAddRemoveRule(ctx->forward_filter,
-                                    VIR_SOCKET_ADDR_FAMILY(netaddr),
-                                    action,
-                                    "--source", networkstr,
-                                    "--in-interface", iface,
-                                    "--jump", "ACCEPT",
-                                    NULL);
-    }
-    VIR_FREE(networkstr);
-    return ret;
-}
-
-/**
- * iptablesAddForwardAllowOut:
- * @ctx: pointer to the IP table context
- * @network: the source network name
- * @iface: the source interface name
- * @physdev: the physical output device
- *
- * Add a rule to the IP table context to allow the traffic for the
- * network @network via interface @iface to be forwarded to
- * @physdev device. This allow the outbound traffic on a bridge.
- *
- * Returns 0 in case of success or an error code otherwise
- */
-int
-iptablesAddForwardAllowOut(iptablesContext *ctx,
-                           virSocketAddr *netaddr,
-                           unsigned int prefix,
-                           const char *iface,
-                           const char *physdev)
-{
-    return iptablesForwardAllowOut(ctx, netaddr, prefix, iface, physdev, ADD);
-}
-
-/**
- * iptablesRemoveForwardAllowOut:
- * @ctx: pointer to the IP table context
- * @network: the source network name
- * @iface: the source interface name
- * @physdev: the physical output device
- *
- * Remove a rule from the IP table context hence forbidding forwarding
- * of the traffic for the network @network via interface @iface
- * to the @physdev device output. This stops the outbound traffic on a bridge.
- *
- * Returns 0 in case of success or an error code otherwise
- */
-int
-iptablesRemoveForwardAllowOut(iptablesContext *ctx,
-                              virSocketAddr *netaddr,
-                              unsigned int prefix,
-                              const char *iface,
-                              const char *physdev)
-{
-    return iptablesForwardAllowOut(ctx, netaddr, prefix, iface, physdev, REMOVE);
-}
-
-
-/* Allow all traffic destined to the bridge, with a valid network address
- * and associated with an existing connection
- */
-static int
-iptablesForwardAllowRelatedIn(iptablesContext *ctx,
-                              virSocketAddr *netaddr,
-                              unsigned int prefix,
-                              const char *iface,
-                              const char *physdev,
-                              int action)
-{
-    int ret;
-    char *networkstr;
-
-    if (!(networkstr = iptablesFormatNetwork(netaddr, prefix)))
-        return -1;
-
-    if (physdev && physdev[0]) {
-        ret = iptablesAddRemoveRule(ctx->forward_filter,
-                                    VIR_SOCKET_ADDR_FAMILY(netaddr),
-                                    action,
-                                    "--destination", networkstr,
-                                    "--in-interface", physdev,
-                                    "--out-interface", iface,
-                                    "--match", "state",
-                                    "--state", "ESTABLISHED,RELATED",
-                                    "--jump", "ACCEPT",
-                                    NULL);
-    } else {
-        ret = iptablesAddRemoveRule(ctx->forward_filter,
-                                    VIR_SOCKET_ADDR_FAMILY(netaddr),
-                                    action,
-                                    "--destination", networkstr,
-                                    "--out-interface", iface,
-                                    "--match", "state",
-                                    "--state", "ESTABLISHED,RELATED",
-                                    "--jump", "ACCEPT",
-                                    NULL);
-    }
-    VIR_FREE(networkstr);
-    return ret;
-}
-
-/**
- * iptablesAddForwardAllowRelatedIn:
- * @ctx: pointer to the IP table context
- * @network: the source network name
- * @iface: the output interface name
- * @physdev: the physical input device or NULL
- *
- * Add rules to the IP table context to allow the traffic for the
- * network @network on @physdev device to be forwarded to
- * interface @iface, if it is part of an existing connection.
- *
- * Returns 0 in case of success or an error code otherwise
- */
-int
-iptablesAddForwardAllowRelatedIn(iptablesContext *ctx,
-                                 virSocketAddr *netaddr,
-                                 unsigned int prefix,
-                                 const char *iface,
-                                 const char *physdev)
-{
-    return iptablesForwardAllowRelatedIn(ctx, netaddr, prefix, iface, physdev, ADD);
-}
-
-/**
- * iptablesRemoveForwardAllowRelatedIn:
- * @ctx: pointer to the IP table context
- * @network: the source network name
- * @iface: the output interface name
- * @physdev: the physical input device or NULL
- *
- * Remove rules from the IP table context hence forbidding the traffic for
- * network @network on @physdev device to be forwarded to
- * interface @iface, if it is part of an existing connection.
- *
- * Returns 0 in case of success or an error code otherwise
- */
-int
-iptablesRemoveForwardAllowRelatedIn(iptablesContext *ctx,
-                                    virSocketAddr *netaddr,
-                                    unsigned int prefix,
-                                    const char *iface,
-                                    const char *physdev)
-{
-    return iptablesForwardAllowRelatedIn(ctx, netaddr, prefix, iface, physdev, REMOVE);
-}
-
-/* Allow all traffic destined to the bridge, with a valid network address
- */
-static int
-iptablesForwardAllowIn(iptablesContext *ctx,
-                       virSocketAddr *netaddr,
-                       unsigned int prefix,
-                       const char *iface,
-                       const char *physdev,
-                       int action)
-{
-    int ret;
-    char *networkstr;
-
-    if (!(networkstr = iptablesFormatNetwork(netaddr, prefix)))
-        return -1;
-
-    if (physdev && physdev[0]) {
-        ret = iptablesAddRemoveRule(ctx->forward_filter,
-                                    VIR_SOCKET_ADDR_FAMILY(netaddr),
-                                    action,
-                                    "--destination", networkstr,
-                                    "--in-interface", physdev,
-                                    "--out-interface", iface,
-                                    "--jump", "ACCEPT",
-                                    NULL);
-    } else {
-        ret = iptablesAddRemoveRule(ctx->forward_filter,
-                                    VIR_SOCKET_ADDR_FAMILY(netaddr),
-                                    action,
-                                    "--destination", networkstr,
-                                    "--out-interface", iface,
-                                    "--jump", "ACCEPT",
-                                    NULL);
-    }
-    VIR_FREE(networkstr);
-    return ret;
-}
-
-/**
- * iptablesAddForwardAllowIn:
- * @ctx: pointer to the IP table context
- * @network: the source network name
- * @iface: the output interface name
- * @physdev: the physical input device or NULL
- *
- * Add rules to the IP table context to allow the traffic for the
- * network @network on @physdev device to be forwarded to
- * interface @iface. This allow the inbound traffic on a bridge.
- *
- * Returns 0 in case of success or an error code otherwise
- */
-int
-iptablesAddForwardAllowIn(iptablesContext *ctx,
-                          virSocketAddr *netaddr,
-                          unsigned int prefix,
-                          const char *iface,
-                          const char *physdev)
-{
-    return iptablesForwardAllowIn(ctx, netaddr, prefix, iface, physdev, ADD);
-}
-
-/**
- * iptablesRemoveForwardAllowIn:
- * @ctx: pointer to the IP table context
- * @network: the source network name
- * @iface: the output interface name
- * @physdev: the physical input device or NULL
- *
- * Remove rules from the IP table context hence forbidding the traffic for
- * network @network on @physdev device to be forwarded to
- * interface @iface. This stops the inbound traffic on a bridge.
- *
- * Returns 0 in case of success or an error code otherwise
- */
-int
-iptablesRemoveForwardAllowIn(iptablesContext *ctx,
-                             virSocketAddr *netaddr,
-                             unsigned int prefix,
-                             const char *iface,
-                             const char *physdev)
-{
-    return iptablesForwardAllowIn(ctx, netaddr, prefix, iface, physdev, REMOVE);
-}
-
-
-/* Allow all traffic between guests on the same bridge,
- * with a valid network address
- */
-static int
-iptablesForwardAllowCross(iptablesContext *ctx,
-                          int family,
-                          const char *iface,
-                          int action)
-{
-    return iptablesAddRemoveRule(ctx->forward_filter,
-                                 family,
-                                 action,
-                                 "--in-interface", iface,
-                                 "--out-interface", iface,
-                                 "--jump", "ACCEPT",
-                                 NULL);
-}
-
-/**
- * iptablesAddForwardAllowCross:
- * @ctx: pointer to the IP table context
- * @iface: the input/output interface name
- *
- * Add rules to the IP table context to allow traffic to cross that
- * interface. It allows all traffic between guests on the same bridge
- * represented by that interface.
- *
- * Returns 0 in case of success or an error code otherwise
- */
-int
-iptablesAddForwardAllowCross(iptablesContext *ctx,
-                             int family,
-                             const char *iface)
-{
-    return iptablesForwardAllowCross(ctx, family, iface, ADD);
-}
-
-/**
- * iptablesRemoveForwardAllowCross:
- * @ctx: pointer to the IP table context
- * @iface: the input/output interface name
- *
- * Remove rules to the IP table context to block traffic to cross that
- * interface. It forbids traffic between guests on the same bridge
- * represented by that interface.
- *
- * Returns 0 in case of success or an error code otherwise
- */
-int
-iptablesRemoveForwardAllowCross(iptablesContext *ctx,
-                                int family,
-                                const char *iface)
-{
-    return iptablesForwardAllowCross(ctx, family, iface, REMOVE);
-}
-
-
-/* Drop all traffic trying to forward from the bridge.
- * ie the bridge is the in interface
- */
-static int
-iptablesForwardRejectOut(iptablesContext *ctx,
-                         int family,
-                         const char *iface,
-                         int action)
-{
-    return iptablesAddRemoveRule(ctx->forward_filter,
-                                 family,
-                                 action,
-                                 "--in-interface", iface,
-                                 "--jump", "REJECT",
-                                 NULL);
-}
-
-/**
- * iptablesAddForwardRejectOut:
- * @ctx: pointer to the IP table context
- * @iface: the output interface name
- *
- * Add rules to the IP table context to forbid all traffic to that
- * interface. It forbids forwarding from the bridge to that interface.
- *
- * Returns 0 in case of success or an error code otherwise
- */
-int
-iptablesAddForwardRejectOut(iptablesContext *ctx,
-                            int family,
-                            const char *iface)
-{
-    return iptablesForwardRejectOut(ctx, family, iface, ADD);
-}
-
-/**
- * iptablesRemoveForwardRejectOut:
- * @ctx: pointer to the IP table context
- * @iface: the output interface name
- *
- * Remove rules from the IP table context forbidding all traffic to that
- * interface. It reallow forwarding from the bridge to that interface.
- *
- * Returns 0 in case of success or an error code otherwise
- */
-int
-iptablesRemoveForwardRejectOut(iptablesContext *ctx,
-                               int family,
-                               const char *iface)
-{
-    return iptablesForwardRejectOut(ctx, family, iface, REMOVE);
-}
-
-
-
-
-/* Drop all traffic trying to forward to the bridge.
- * ie the bridge is the out interface
- */
-static int
-iptablesForwardRejectIn(iptablesContext *ctx,
-                        int family,
-                        const char *iface,
-                        int action)
-{
-    return iptablesAddRemoveRule(ctx->forward_filter,
-                                 family,
-                                 action,
-                                 "--out-interface", iface,
-                                 "--jump", "REJECT",
-                                 NULL);
-}
-
-/**
- * iptablesAddForwardRejectIn:
- * @ctx: pointer to the IP table context
- * @iface: the input interface name
- *
- * Add rules to the IP table context to forbid all traffic from that
- * interface. It forbids forwarding from that interface to the bridge.
- *
- * Returns 0 in case of success or an error code otherwise
- */
-int
-iptablesAddForwardRejectIn(iptablesContext *ctx,
-                           int family,
-                           const char *iface)
-{
-    return iptablesForwardRejectIn(ctx, family, iface, ADD);
-}
-
-/**
- * iptablesRemoveForwardRejectIn:
- * @ctx: pointer to the IP table context
- * @iface: the input interface name
- *
- * Remove rules from the IP table context forbidding all traffic from that
- * interface. It allows forwarding from that interface to the bridge.
- *
- * Returns 0 in case of success or an error code otherwise
- */
-int
-iptablesRemoveForwardRejectIn(iptablesContext *ctx,
-                              int family,
-                              const char *iface)
-{
-    return iptablesForwardRejectIn(ctx, family, iface, REMOVE);
-}
-
-
-/* Masquerade all traffic coming from the network associated
- * with the bridge
- */
-static int
-iptablesForwardMasquerade(iptablesContext *ctx,
-                          virSocketAddr *netaddr,
-                          unsigned int prefix,
-                          const char *physdev,
-                          const char *protocol,
-                          int action)
-{
-    int ret;
-    char *networkstr;
-
-    if (!(networkstr = iptablesFormatNetwork(netaddr, prefix)))
-        return -1;
-
-    if (!VIR_SOCKET_ADDR_IS_FAMILY(netaddr, AF_INET)) {
-        /* Higher level code *should* guaranteee it's impossible to get here. */
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("Attempted to NAT '%s'. NAT is only supported for IPv4."),
-                       networkstr);
-        VIR_FREE(networkstr);
-        return -1;
-    }
-
-    if (protocol && protocol[0]) {
-        if (physdev && physdev[0]) {
-            ret = iptablesAddRemoveRule(ctx->nat_postrouting,
-                                        AF_INET,
-                                        action,
-                                        "--source", networkstr,
-                                        "-p", protocol,
-                                        "!", "--destination", networkstr,
-                                        "--out-interface", physdev,
-                                        "--jump", "MASQUERADE",
-                                        "--to-ports", "1024-65535",
-                                        NULL);
-        } else {
-            ret = iptablesAddRemoveRule(ctx->nat_postrouting,
-                                        AF_INET,
-                                        action,
-                                        "--source", networkstr,
-                                        "-p", protocol,
-                                        "!", "--destination", networkstr,
-                                        "--jump", "MASQUERADE",
-                                        "--to-ports", "1024-65535",
-                                        NULL);
-        }
-    } else {
-        if (physdev && physdev[0]) {
-            ret = iptablesAddRemoveRule(ctx->nat_postrouting,
-                                        AF_INET,
-                                        action,
-                                        "--source", networkstr,
-                                        "!", "--destination", networkstr,
-                                        "--out-interface", physdev,
-                                        "--jump", "MASQUERADE",
-                                        NULL);
-        } else {
-            ret = iptablesAddRemoveRule(ctx->nat_postrouting,
-                                        AF_INET,
-                                        action,
-                                        "--source", networkstr,
-                                        "!", "--destination", networkstr,
-                                        "--jump", "MASQUERADE",
-                                        NULL);
-        }
-    }
-    VIR_FREE(networkstr);
-    return ret;
-}
-
-/**
- * iptablesAddForwardMasquerade:
- * @ctx: pointer to the IP table context
- * @network: the source network name
- * @physdev: the physical input device or NULL
- * @protocol: the network protocol or NULL
- *
- * Add rules to the IP table context to allow masquerading
- * network @network on @physdev. This allow the bridge to
- * masquerade for that network (on @physdev).
- *
- * Returns 0 in case of success or an error code otherwise
- */
-int
-iptablesAddForwardMasquerade(iptablesContext *ctx,
-                             virSocketAddr *netaddr,
-                             unsigned int prefix,
-                             const char *physdev,
-                             const char *protocol)
-{
-    return iptablesForwardMasquerade(ctx, netaddr, prefix, physdev, protocol, ADD);
-}
-
-/**
- * iptablesRemoveForwardMasquerade:
- * @ctx: pointer to the IP table context
- * @network: the source network name
- * @physdev: the physical input device or NULL
- * @protocol: the network protocol or NULL
- *
- * Remove rules from the IP table context to stop masquerading
- * network @network on @physdev. This stops the bridge from
- * masquerading for that network (on @physdev).
- *
- * Returns 0 in case of success or an error code otherwise
- */
-int
-iptablesRemoveForwardMasquerade(iptablesContext *ctx,
-                                virSocketAddr *netaddr,
-                                unsigned int prefix,
-                                const char *physdev,
-                                const char *protocol)
-{
-    return iptablesForwardMasquerade(ctx, netaddr, prefix, physdev, protocol, REMOVE);
-}
-
-
-static int
-iptablesOutputFixUdpChecksum(iptablesContext *ctx,
-                             const char *iface,
-                             int port,
-                             int action)
-{
-    char portstr[32];
-
-    snprintf(portstr, sizeof(portstr), "%d", port);
-    portstr[sizeof(portstr) - 1] = '\0';
-
-    return iptablesAddRemoveRule(ctx->mangle_postrouting,
-                                 AF_INET,
-                                 action,
-                                 "--out-interface", iface,
-                                 "--protocol", "udp",
-                                 "--destination-port", portstr,
-                                 "--jump", "CHECKSUM", "--checksum-fill",
-                                 NULL);
-}
-
-/**
- * iptablesAddOutputFixUdpChecksum:
- * @ctx: pointer to the IP table context
- * @iface: the interface name
- * @port: the UDP port to match
- *
- * Add a rule to the mangle table's POSTROUTING chain that fixes up the
- * checksum of packets with the given destination @port.
- * the given @iface interface for TCP packets.
- *
- * Returns 0 in case of success or an error code in case of error.
- * (NB: if the system's iptables does not support checksum mangling,
- * this will return an error, which should be ignored.)
- */
-
-int
-iptablesAddOutputFixUdpChecksum(iptablesContext *ctx,
-                                const char *iface,
-                                int port)
-{
-    return iptablesOutputFixUdpChecksum(ctx, iface, port, ADD);
-}
-
-/**
- * iptablesRemoveOutputFixUdpChecksum:
- * @ctx: pointer to the IP table context
- * @iface: the interface name
- * @port: the UDP port of the rule to remove
- *
- * Removes the checksum fixup rule that was previous added with
- * iptablesAddOutputFixUdpChecksum.
- *
- * Returns 0 in case of success or an error code in case of error
- * (again, if iptables doesn't support checksum fixup, this will
- * return an error, which should be ignored)
- */
-int
-iptablesRemoveOutputFixUdpChecksum(iptablesContext *ctx,
-                                   const char *iface,
-                                   int port)
-{
-    return iptablesOutputFixUdpChecksum(ctx, iface, port, REMOVE);
-}
diff --git a/src/util/iptables.h b/src/util/iptables.h
deleted file mode 100644
index e54f8b1..0000000
--- a/src/util/iptables.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2007, 2008 Red Hat, Inc.
- *
- * 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/>.
- *
- * Authors:
- *     Mark McLoughlin <markmc at redhat.com>
- */
-
-#ifndef __QEMUD_IPTABLES_H__
-# define __QEMUD_IPTABLES_H__
-
-# include "virsocketaddr.h"
-
-typedef struct _iptablesContext iptablesContext;
-
-iptablesContext *iptablesContextNew              (void);
-void             iptablesContextFree             (iptablesContext *ctx);
-
-int              iptablesAddTcpInput             (iptablesContext *ctx,
-                                                  int family,
-                                                  const char *iface,
-                                                  int port);
-int              iptablesRemoveTcpInput          (iptablesContext *ctx,
-                                                  int family,
-                                                  const char *iface,
-                                                  int port);
-
-int              iptablesAddUdpInput             (iptablesContext *ctx,
-                                                  int family,
-                                                  const char *iface,
-                                                  int port);
-int              iptablesRemoveUdpInput          (iptablesContext *ctx,
-                                                  int family,
-                                                  const char *iface,
-                                                  int port);
-
-int              iptablesAddForwardAllowOut      (iptablesContext *ctx,
-                                                  virSocketAddr *netaddr,
-                                                  unsigned int prefix,
-                                                  const char *iface,
-                                                  const char *physdev);
-int              iptablesRemoveForwardAllowOut   (iptablesContext *ctx,
-                                                  virSocketAddr *netaddr,
-                                                  unsigned int prefix,
-                                                  const char *iface,
-                                                  const char *physdev);
-
-int              iptablesAddForwardAllowRelatedIn(iptablesContext *ctx,
-                                                  virSocketAddr *netaddr,
-                                                  unsigned int prefix,
-                                                  const char *iface,
-                                                  const char *physdev);
-int              iptablesRemoveForwardAllowRelatedIn(iptablesContext *ctx,
-                                                  virSocketAddr *netaddr,
-                                                  unsigned int prefix,
-                                                  const char *iface,
-                                                  const char *physdev);
-
-int              iptablesAddForwardAllowIn       (iptablesContext *ctx,
-                                                  virSocketAddr *netaddr,
-                                                  unsigned int prefix,
-                                                  const char *iface,
-                                                  const char *physdev);
-int              iptablesRemoveForwardAllowIn    (iptablesContext *ctx,
-                                                  virSocketAddr *netaddr,
-                                                  unsigned int prefix,
-                                                  const char *iface,
-                                                  const char *physdev);
-
-int              iptablesAddForwardAllowCross    (iptablesContext *ctx,
-                                                  int family,
-                                                  const char *iface);
-int              iptablesRemoveForwardAllowCross (iptablesContext *ctx,
-                                                  int family,
-                                                  const char *iface);
-
-int              iptablesAddForwardRejectOut     (iptablesContext *ctx,
-                                                  int family,
-                                                  const char *iface);
-int              iptablesRemoveForwardRejectOut  (iptablesContext *ctx,
-                                                  int family,
-                                                  const char *iface);
-
-int              iptablesAddForwardRejectIn      (iptablesContext *ctx,
-                                                  int family,
-                                                  const char *iface);
-int              iptablesRemoveForwardRejectIn   (iptablesContext *ctx,
-                                                  int family,
-                                                  const char *iface);
-
-int              iptablesAddForwardMasquerade    (iptablesContext *ctx,
-                                                  virSocketAddr *netaddr,
-                                                  unsigned int prefix,
-                                                  const char *physdev,
-                                                  const char *protocol);
-int              iptablesRemoveForwardMasquerade (iptablesContext *ctx,
-                                                  virSocketAddr *netaddr,
-                                                  unsigned int prefix,
-                                                  const char *physdev,
-                                                  const char *protocol);
-int              iptablesAddOutputFixUdpChecksum (iptablesContext *ctx,
-                                                  const char *iface,
-                                                  int port);
-int              iptablesRemoveOutputFixUdpChecksum (iptablesContext *ctx,
-                                                     const char *iface,
-                                                     int port);
-
-#endif /* __QEMUD_IPTABLES_H__ */
diff --git a/src/util/viriptables.c b/src/util/viriptables.c
new file mode 100644
index 0000000..8831920
--- /dev/null
+++ b/src/util/viriptables.c
@@ -0,0 +1,970 @@
+/*
+ * Copyright (C) 2007-2012 Red Hat, Inc.
+ *
+ * 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/>.
+ *
+ * Authors:
+ *     Mark McLoughlin <markmc at redhat.com>
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#ifdef HAVE_PATHS_H
+# include <paths.h>
+#endif
+
+#include "internal.h"
+#include "viriptables.h"
+#include "vircommand.h"
+#include "memory.h"
+#include "virterror_internal.h"
+#include "logging.h"
+#include "threads.h"
+
+#if HAVE_FIREWALLD
+static char *firewall_cmd_path = NULL;
+
+static int
+virIpTablesOnceInit(void)
+{
+    firewall_cmd_path = virFindFileInPath("firewall-cmd");
+    if (!firewall_cmd_path) {
+        VIR_INFO("firewall-cmd not found on system. "
+                 "firewalld support disabled for iptables.");
+    } else {
+        virCommandPtr cmd = virCommandNew(firewall_cmd_path);
+        int status;
+
+        virCommandAddArgList(cmd, "--state", NULL);
+        if (virCommandRun(cmd, &status) < 0 || status != 0) {
+            VIR_INFO("firewall-cmd found but disabled for iptables");
+            VIR_FREE(firewall_cmd_path);
+            firewall_cmd_path = NULL;
+        } else {
+            VIR_INFO("using firewalld for iptables commands");
+        }
+        virCommandFree(cmd);
+    }
+    return 0;
+}
+
+VIR_ONCE_GLOBAL_INIT(virIpTables)
+
+#endif
+
+#define VIR_FROM_THIS VIR_FROM_NONE
+
+enum {
+    ADD = 0,
+    REMOVE
+};
+
+typedef struct
+{
+    char  *table;
+    char  *chain;
+} iptRules;
+
+struct _iptablesContext
+{
+    iptRules *input_filter;
+    iptRules *forward_filter;
+    iptRules *nat_postrouting;
+    iptRules *mangle_postrouting;
+};
+
+static void
+iptRulesFree(iptRules *rules)
+{
+    VIR_FREE(rules->table);
+    VIR_FREE(rules->chain);
+    VIR_FREE(rules);
+}
+
+static iptRules *
+iptRulesNew(const char *table,
+            const char *chain)
+{
+    iptRules *rules;
+
+    if (VIR_ALLOC(rules) < 0)
+        return NULL;
+
+    if (!(rules->table = strdup(table)))
+        goto error;
+
+    if (!(rules->chain = strdup(chain)))
+        goto error;
+
+    return rules;
+
+ error:
+    iptRulesFree(rules);
+    return NULL;
+}
+
+static int ATTRIBUTE_SENTINEL
+iptablesAddRemoveRule(iptRules *rules, int family, int action,
+                      const char *arg, ...)
+{
+    va_list args;
+    int ret;
+    virCommandPtr cmd = NULL;
+    const char *s;
+
+#if HAVE_FIREWALLD
+    virIpTablesInitialize();
+    if (firewall_cmd_path) {
+        cmd = virCommandNew(firewall_cmd_path);
+        virCommandAddArgList(cmd, "--direct", "--passthrough",
+                             (family == AF_INET6) ? "ipv6" : "ipv4", NULL);
+    }
+#endif
+
+    if (cmd == NULL) {
+        cmd = virCommandNew((family == AF_INET6)
+                        ? IP6TABLES_PATH : IPTABLES_PATH);
+    }
+
+    virCommandAddArgList(cmd, "--table", rules->table,
+                         action == ADD ? "--insert" : "--delete",
+                         rules->chain, arg, NULL);
+
+    va_start(args, arg);
+    while ((s = va_arg(args, const char *)))
+        virCommandAddArg(cmd, s);
+    va_end(args);
+
+    ret = virCommandRun(cmd, NULL);
+    virCommandFree(cmd);
+    return ret;
+}
+
+/**
+ * iptablesContextNew:
+ *
+ * Create a new IPtable context
+ *
+ * Returns a pointer to the new structure or NULL in case of error
+ */
+iptablesContext *
+iptablesContextNew(void)
+{
+    iptablesContext *ctx;
+
+    if (VIR_ALLOC(ctx) < 0)
+        return NULL;
+
+    if (!(ctx->input_filter = iptRulesNew("filter", "INPUT")))
+        goto error;
+
+    if (!(ctx->forward_filter = iptRulesNew("filter", "FORWARD")))
+        goto error;
+
+    if (!(ctx->nat_postrouting = iptRulesNew("nat", "POSTROUTING")))
+        goto error;
+
+    if (!(ctx->mangle_postrouting = iptRulesNew("mangle", "POSTROUTING")))
+        goto error;
+
+    return ctx;
+
+ error:
+    iptablesContextFree(ctx);
+    return NULL;
+}
+
+/**
+ * iptablesContextFree:
+ * @ctx: pointer to the IP table context
+ *
+ * Free the resources associated with an IP table context
+ */
+void
+iptablesContextFree(iptablesContext *ctx)
+{
+    if (ctx->input_filter)
+        iptRulesFree(ctx->input_filter);
+    if (ctx->forward_filter)
+        iptRulesFree(ctx->forward_filter);
+    if (ctx->nat_postrouting)
+        iptRulesFree(ctx->nat_postrouting);
+    if (ctx->mangle_postrouting)
+        iptRulesFree(ctx->mangle_postrouting);
+    VIR_FREE(ctx);
+}
+
+static int
+iptablesInput(iptablesContext *ctx,
+              int family,
+              const char *iface,
+              int port,
+              int action,
+              int tcp)
+{
+    char portstr[32];
+
+    snprintf(portstr, sizeof(portstr), "%d", port);
+    portstr[sizeof(portstr) - 1] = '\0';
+
+    return iptablesAddRemoveRule(ctx->input_filter,
+                                 family,
+                                 action,
+                                 "--in-interface", iface,
+                                 "--protocol", tcp ? "tcp" : "udp",
+                                 "--destination-port", portstr,
+                                 "--jump", "ACCEPT",
+                                 NULL);
+}
+
+/**
+ * iptablesAddTcpInput:
+ * @ctx: pointer to the IP table context
+ * @iface: the interface name
+ * @port: the TCP port to add
+ *
+ * Add an input to the IP table allowing access to the given @port on
+ * the given @iface interface for TCP packets
+ *
+ * Returns 0 in case of success or an error code in case of error
+ */
+
+int
+iptablesAddTcpInput(iptablesContext *ctx,
+                    int family,
+                    const char *iface,
+                    int port)
+{
+    return iptablesInput(ctx, family, iface, port, ADD, 1);
+}
+
+/**
+ * iptablesRemoveTcpInput:
+ * @ctx: pointer to the IP table context
+ * @iface: the interface name
+ * @port: the TCP port to remove
+ *
+ * Removes an input from the IP table, hence forbidding access to the given
+ * @port on the given @iface interface for TCP packets
+ *
+ * Returns 0 in case of success or an error code in case of error
+ */
+int
+iptablesRemoveTcpInput(iptablesContext *ctx,
+                       int family,
+                       const char *iface,
+                       int port)
+{
+    return iptablesInput(ctx, family, iface, port, REMOVE, 1);
+}
+
+/**
+ * iptablesAddUdpInput:
+ * @ctx: pointer to the IP table context
+ * @iface: the interface name
+ * @port: the UDP port to add
+ *
+ * Add an input to the IP table allowing access to the given @port on
+ * the given @iface interface for UDP packets
+ *
+ * Returns 0 in case of success or an error code in case of error
+ */
+
+int
+iptablesAddUdpInput(iptablesContext *ctx,
+                    int family,
+                    const char *iface,
+                    int port)
+{
+    return iptablesInput(ctx, family, iface, port, ADD, 0);
+}
+
+/**
+ * iptablesRemoveUdpInput:
+ * @ctx: pointer to the IP table context
+ * @iface: the interface name
+ * @port: the UDP port to remove
+ *
+ * Removes an input from the IP table, hence forbidding access to the given
+ * @port on the given @iface interface for UDP packets
+ *
+ * Returns 0 in case of success or an error code in case of error
+ */
+int
+iptablesRemoveUdpInput(iptablesContext *ctx,
+                       int family,
+                       const char *iface,
+                       int port)
+{
+    return iptablesInput(ctx, family, iface, port, REMOVE, 0);
+}
+
+
+static char *iptablesFormatNetwork(virSocketAddr *netaddr,
+                                   unsigned int prefix)
+{
+    virSocketAddr network;
+    char *netstr;
+    char *ret;
+
+    if (!(VIR_SOCKET_ADDR_IS_FAMILY(netaddr, AF_INET) ||
+          VIR_SOCKET_ADDR_IS_FAMILY(netaddr, AF_INET6))) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Only IPv4 or IPv6 addresses can be used with iptables"));
+        return NULL;
+    }
+
+    if (virSocketAddrMaskByPrefix(netaddr, prefix, &network) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("Failure to mask address"));
+        return NULL;
+    }
+
+    netstr = virSocketAddrFormat(&network);
+
+    if (!netstr)
+        return NULL;
+
+    if (virAsprintf(&ret, "%s/%d", netstr, prefix) < 0)
+        virReportOOMError();
+
+    VIR_FREE(netstr);
+    return ret;
+}
+
+
+/* Allow all traffic coming from the bridge, with a valid network address
+ * to proceed to WAN
+ */
+static int
+iptablesForwardAllowOut(iptablesContext *ctx,
+                        virSocketAddr *netaddr,
+                        unsigned int prefix,
+                        const char *iface,
+                        const char *physdev,
+                        int action)
+{
+    int ret;
+    char *networkstr;
+
+    if (!(networkstr = iptablesFormatNetwork(netaddr, prefix)))
+        return -1;
+
+    if (physdev && physdev[0]) {
+        ret = iptablesAddRemoveRule(ctx->forward_filter,
+                                    VIR_SOCKET_ADDR_FAMILY(netaddr),
+                                    action,
+                                    "--source", networkstr,
+                                    "--in-interface", iface,
+                                    "--out-interface", physdev,
+                                    "--jump", "ACCEPT",
+                                    NULL);
+    } else {
+        ret = iptablesAddRemoveRule(ctx->forward_filter,
+                                    VIR_SOCKET_ADDR_FAMILY(netaddr),
+                                    action,
+                                    "--source", networkstr,
+                                    "--in-interface", iface,
+                                    "--jump", "ACCEPT",
+                                    NULL);
+    }
+    VIR_FREE(networkstr);
+    return ret;
+}
+
+/**
+ * iptablesAddForwardAllowOut:
+ * @ctx: pointer to the IP table context
+ * @network: the source network name
+ * @iface: the source interface name
+ * @physdev: the physical output device
+ *
+ * Add a rule to the IP table context to allow the traffic for the
+ * network @network via interface @iface to be forwarded to
+ * @physdev device. This allow the outbound traffic on a bridge.
+ *
+ * Returns 0 in case of success or an error code otherwise
+ */
+int
+iptablesAddForwardAllowOut(iptablesContext *ctx,
+                           virSocketAddr *netaddr,
+                           unsigned int prefix,
+                           const char *iface,
+                           const char *physdev)
+{
+    return iptablesForwardAllowOut(ctx, netaddr, prefix, iface, physdev, ADD);
+}
+
+/**
+ * iptablesRemoveForwardAllowOut:
+ * @ctx: pointer to the IP table context
+ * @network: the source network name
+ * @iface: the source interface name
+ * @physdev: the physical output device
+ *
+ * Remove a rule from the IP table context hence forbidding forwarding
+ * of the traffic for the network @network via interface @iface
+ * to the @physdev device output. This stops the outbound traffic on a bridge.
+ *
+ * Returns 0 in case of success or an error code otherwise
+ */
+int
+iptablesRemoveForwardAllowOut(iptablesContext *ctx,
+                              virSocketAddr *netaddr,
+                              unsigned int prefix,
+                              const char *iface,
+                              const char *physdev)
+{
+    return iptablesForwardAllowOut(ctx, netaddr, prefix, iface, physdev, REMOVE);
+}
+
+
+/* Allow all traffic destined to the bridge, with a valid network address
+ * and associated with an existing connection
+ */
+static int
+iptablesForwardAllowRelatedIn(iptablesContext *ctx,
+                              virSocketAddr *netaddr,
+                              unsigned int prefix,
+                              const char *iface,
+                              const char *physdev,
+                              int action)
+{
+    int ret;
+    char *networkstr;
+
+    if (!(networkstr = iptablesFormatNetwork(netaddr, prefix)))
+        return -1;
+
+    if (physdev && physdev[0]) {
+        ret = iptablesAddRemoveRule(ctx->forward_filter,
+                                    VIR_SOCKET_ADDR_FAMILY(netaddr),
+                                    action,
+                                    "--destination", networkstr,
+                                    "--in-interface", physdev,
+                                    "--out-interface", iface,
+                                    "--match", "state",
+                                    "--state", "ESTABLISHED,RELATED",
+                                    "--jump", "ACCEPT",
+                                    NULL);
+    } else {
+        ret = iptablesAddRemoveRule(ctx->forward_filter,
+                                    VIR_SOCKET_ADDR_FAMILY(netaddr),
+                                    action,
+                                    "--destination", networkstr,
+                                    "--out-interface", iface,
+                                    "--match", "state",
+                                    "--state", "ESTABLISHED,RELATED",
+                                    "--jump", "ACCEPT",
+                                    NULL);
+    }
+    VIR_FREE(networkstr);
+    return ret;
+}
+
+/**
+ * iptablesAddForwardAllowRelatedIn:
+ * @ctx: pointer to the IP table context
+ * @network: the source network name
+ * @iface: the output interface name
+ * @physdev: the physical input device or NULL
+ *
+ * Add rules to the IP table context to allow the traffic for the
+ * network @network on @physdev device to be forwarded to
+ * interface @iface, if it is part of an existing connection.
+ *
+ * Returns 0 in case of success or an error code otherwise
+ */
+int
+iptablesAddForwardAllowRelatedIn(iptablesContext *ctx,
+                                 virSocketAddr *netaddr,
+                                 unsigned int prefix,
+                                 const char *iface,
+                                 const char *physdev)
+{
+    return iptablesForwardAllowRelatedIn(ctx, netaddr, prefix, iface, physdev, ADD);
+}
+
+/**
+ * iptablesRemoveForwardAllowRelatedIn:
+ * @ctx: pointer to the IP table context
+ * @network: the source network name
+ * @iface: the output interface name
+ * @physdev: the physical input device or NULL
+ *
+ * Remove rules from the IP table context hence forbidding the traffic for
+ * network @network on @physdev device to be forwarded to
+ * interface @iface, if it is part of an existing connection.
+ *
+ * Returns 0 in case of success or an error code otherwise
+ */
+int
+iptablesRemoveForwardAllowRelatedIn(iptablesContext *ctx,
+                                    virSocketAddr *netaddr,
+                                    unsigned int prefix,
+                                    const char *iface,
+                                    const char *physdev)
+{
+    return iptablesForwardAllowRelatedIn(ctx, netaddr, prefix, iface, physdev, REMOVE);
+}
+
+/* Allow all traffic destined to the bridge, with a valid network address
+ */
+static int
+iptablesForwardAllowIn(iptablesContext *ctx,
+                       virSocketAddr *netaddr,
+                       unsigned int prefix,
+                       const char *iface,
+                       const char *physdev,
+                       int action)
+{
+    int ret;
+    char *networkstr;
+
+    if (!(networkstr = iptablesFormatNetwork(netaddr, prefix)))
+        return -1;
+
+    if (physdev && physdev[0]) {
+        ret = iptablesAddRemoveRule(ctx->forward_filter,
+                                    VIR_SOCKET_ADDR_FAMILY(netaddr),
+                                    action,
+                                    "--destination", networkstr,
+                                    "--in-interface", physdev,
+                                    "--out-interface", iface,
+                                    "--jump", "ACCEPT",
+                                    NULL);
+    } else {
+        ret = iptablesAddRemoveRule(ctx->forward_filter,
+                                    VIR_SOCKET_ADDR_FAMILY(netaddr),
+                                    action,
+                                    "--destination", networkstr,
+                                    "--out-interface", iface,
+                                    "--jump", "ACCEPT",
+                                    NULL);
+    }
+    VIR_FREE(networkstr);
+    return ret;
+}
+
+/**
+ * iptablesAddForwardAllowIn:
+ * @ctx: pointer to the IP table context
+ * @network: the source network name
+ * @iface: the output interface name
+ * @physdev: the physical input device or NULL
+ *
+ * Add rules to the IP table context to allow the traffic for the
+ * network @network on @physdev device to be forwarded to
+ * interface @iface. This allow the inbound traffic on a bridge.
+ *
+ * Returns 0 in case of success or an error code otherwise
+ */
+int
+iptablesAddForwardAllowIn(iptablesContext *ctx,
+                          virSocketAddr *netaddr,
+                          unsigned int prefix,
+                          const char *iface,
+                          const char *physdev)
+{
+    return iptablesForwardAllowIn(ctx, netaddr, prefix, iface, physdev, ADD);
+}
+
+/**
+ * iptablesRemoveForwardAllowIn:
+ * @ctx: pointer to the IP table context
+ * @network: the source network name
+ * @iface: the output interface name
+ * @physdev: the physical input device or NULL
+ *
+ * Remove rules from the IP table context hence forbidding the traffic for
+ * network @network on @physdev device to be forwarded to
+ * interface @iface. This stops the inbound traffic on a bridge.
+ *
+ * Returns 0 in case of success or an error code otherwise
+ */
+int
+iptablesRemoveForwardAllowIn(iptablesContext *ctx,
+                             virSocketAddr *netaddr,
+                             unsigned int prefix,
+                             const char *iface,
+                             const char *physdev)
+{
+    return iptablesForwardAllowIn(ctx, netaddr, prefix, iface, physdev, REMOVE);
+}
+
+
+/* Allow all traffic between guests on the same bridge,
+ * with a valid network address
+ */
+static int
+iptablesForwardAllowCross(iptablesContext *ctx,
+                          int family,
+                          const char *iface,
+                          int action)
+{
+    return iptablesAddRemoveRule(ctx->forward_filter,
+                                 family,
+                                 action,
+                                 "--in-interface", iface,
+                                 "--out-interface", iface,
+                                 "--jump", "ACCEPT",
+                                 NULL);
+}
+
+/**
+ * iptablesAddForwardAllowCross:
+ * @ctx: pointer to the IP table context
+ * @iface: the input/output interface name
+ *
+ * Add rules to the IP table context to allow traffic to cross that
+ * interface. It allows all traffic between guests on the same bridge
+ * represented by that interface.
+ *
+ * Returns 0 in case of success or an error code otherwise
+ */
+int
+iptablesAddForwardAllowCross(iptablesContext *ctx,
+                             int family,
+                             const char *iface)
+{
+    return iptablesForwardAllowCross(ctx, family, iface, ADD);
+}
+
+/**
+ * iptablesRemoveForwardAllowCross:
+ * @ctx: pointer to the IP table context
+ * @iface: the input/output interface name
+ *
+ * Remove rules to the IP table context to block traffic to cross that
+ * interface. It forbids traffic between guests on the same bridge
+ * represented by that interface.
+ *
+ * Returns 0 in case of success or an error code otherwise
+ */
+int
+iptablesRemoveForwardAllowCross(iptablesContext *ctx,
+                                int family,
+                                const char *iface)
+{
+    return iptablesForwardAllowCross(ctx, family, iface, REMOVE);
+}
+
+
+/* Drop all traffic trying to forward from the bridge.
+ * ie the bridge is the in interface
+ */
+static int
+iptablesForwardRejectOut(iptablesContext *ctx,
+                         int family,
+                         const char *iface,
+                         int action)
+{
+    return iptablesAddRemoveRule(ctx->forward_filter,
+                                 family,
+                                 action,
+                                 "--in-interface", iface,
+                                 "--jump", "REJECT",
+                                 NULL);
+}
+
+/**
+ * iptablesAddForwardRejectOut:
+ * @ctx: pointer to the IP table context
+ * @iface: the output interface name
+ *
+ * Add rules to the IP table context to forbid all traffic to that
+ * interface. It forbids forwarding from the bridge to that interface.
+ *
+ * Returns 0 in case of success or an error code otherwise
+ */
+int
+iptablesAddForwardRejectOut(iptablesContext *ctx,
+                            int family,
+                            const char *iface)
+{
+    return iptablesForwardRejectOut(ctx, family, iface, ADD);
+}
+
+/**
+ * iptablesRemoveForwardRejectOut:
+ * @ctx: pointer to the IP table context
+ * @iface: the output interface name
+ *
+ * Remove rules from the IP table context forbidding all traffic to that
+ * interface. It reallow forwarding from the bridge to that interface.
+ *
+ * Returns 0 in case of success or an error code otherwise
+ */
+int
+iptablesRemoveForwardRejectOut(iptablesContext *ctx,
+                               int family,
+                               const char *iface)
+{
+    return iptablesForwardRejectOut(ctx, family, iface, REMOVE);
+}
+
+
+
+
+/* Drop all traffic trying to forward to the bridge.
+ * ie the bridge is the out interface
+ */
+static int
+iptablesForwardRejectIn(iptablesContext *ctx,
+                        int family,
+                        const char *iface,
+                        int action)
+{
+    return iptablesAddRemoveRule(ctx->forward_filter,
+                                 family,
+                                 action,
+                                 "--out-interface", iface,
+                                 "--jump", "REJECT",
+                                 NULL);
+}
+
+/**
+ * iptablesAddForwardRejectIn:
+ * @ctx: pointer to the IP table context
+ * @iface: the input interface name
+ *
+ * Add rules to the IP table context to forbid all traffic from that
+ * interface. It forbids forwarding from that interface to the bridge.
+ *
+ * Returns 0 in case of success or an error code otherwise
+ */
+int
+iptablesAddForwardRejectIn(iptablesContext *ctx,
+                           int family,
+                           const char *iface)
+{
+    return iptablesForwardRejectIn(ctx, family, iface, ADD);
+}
+
+/**
+ * iptablesRemoveForwardRejectIn:
+ * @ctx: pointer to the IP table context
+ * @iface: the input interface name
+ *
+ * Remove rules from the IP table context forbidding all traffic from that
+ * interface. It allows forwarding from that interface to the bridge.
+ *
+ * Returns 0 in case of success or an error code otherwise
+ */
+int
+iptablesRemoveForwardRejectIn(iptablesContext *ctx,
+                              int family,
+                              const char *iface)
+{
+    return iptablesForwardRejectIn(ctx, family, iface, REMOVE);
+}
+
+
+/* Masquerade all traffic coming from the network associated
+ * with the bridge
+ */
+static int
+iptablesForwardMasquerade(iptablesContext *ctx,
+                          virSocketAddr *netaddr,
+                          unsigned int prefix,
+                          const char *physdev,
+                          const char *protocol,
+                          int action)
+{
+    int ret;
+    char *networkstr;
+
+    if (!(networkstr = iptablesFormatNetwork(netaddr, prefix)))
+        return -1;
+
+    if (!VIR_SOCKET_ADDR_IS_FAMILY(netaddr, AF_INET)) {
+        /* Higher level code *should* guaranteee it's impossible to get here. */
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Attempted to NAT '%s'. NAT is only supported for IPv4."),
+                       networkstr);
+        VIR_FREE(networkstr);
+        return -1;
+    }
+
+    if (protocol && protocol[0]) {
+        if (physdev && physdev[0]) {
+            ret = iptablesAddRemoveRule(ctx->nat_postrouting,
+                                        AF_INET,
+                                        action,
+                                        "--source", networkstr,
+                                        "-p", protocol,
+                                        "!", "--destination", networkstr,
+                                        "--out-interface", physdev,
+                                        "--jump", "MASQUERADE",
+                                        "--to-ports", "1024-65535",
+                                        NULL);
+        } else {
+            ret = iptablesAddRemoveRule(ctx->nat_postrouting,
+                                        AF_INET,
+                                        action,
+                                        "--source", networkstr,
+                                        "-p", protocol,
+                                        "!", "--destination", networkstr,
+                                        "--jump", "MASQUERADE",
+                                        "--to-ports", "1024-65535",
+                                        NULL);
+        }
+    } else {
+        if (physdev && physdev[0]) {
+            ret = iptablesAddRemoveRule(ctx->nat_postrouting,
+                                        AF_INET,
+                                        action,
+                                        "--source", networkstr,
+                                        "!", "--destination", networkstr,
+                                        "--out-interface", physdev,
+                                        "--jump", "MASQUERADE",
+                                        NULL);
+        } else {
+            ret = iptablesAddRemoveRule(ctx->nat_postrouting,
+                                        AF_INET,
+                                        action,
+                                        "--source", networkstr,
+                                        "!", "--destination", networkstr,
+                                        "--jump", "MASQUERADE",
+                                        NULL);
+        }
+    }
+    VIR_FREE(networkstr);
+    return ret;
+}
+
+/**
+ * iptablesAddForwardMasquerade:
+ * @ctx: pointer to the IP table context
+ * @network: the source network name
+ * @physdev: the physical input device or NULL
+ * @protocol: the network protocol or NULL
+ *
+ * Add rules to the IP table context to allow masquerading
+ * network @network on @physdev. This allow the bridge to
+ * masquerade for that network (on @physdev).
+ *
+ * Returns 0 in case of success or an error code otherwise
+ */
+int
+iptablesAddForwardMasquerade(iptablesContext *ctx,
+                             virSocketAddr *netaddr,
+                             unsigned int prefix,
+                             const char *physdev,
+                             const char *protocol)
+{
+    return iptablesForwardMasquerade(ctx, netaddr, prefix, physdev, protocol, ADD);
+}
+
+/**
+ * iptablesRemoveForwardMasquerade:
+ * @ctx: pointer to the IP table context
+ * @network: the source network name
+ * @physdev: the physical input device or NULL
+ * @protocol: the network protocol or NULL
+ *
+ * Remove rules from the IP table context to stop masquerading
+ * network @network on @physdev. This stops the bridge from
+ * masquerading for that network (on @physdev).
+ *
+ * Returns 0 in case of success or an error code otherwise
+ */
+int
+iptablesRemoveForwardMasquerade(iptablesContext *ctx,
+                                virSocketAddr *netaddr,
+                                unsigned int prefix,
+                                const char *physdev,
+                                const char *protocol)
+{
+    return iptablesForwardMasquerade(ctx, netaddr, prefix, physdev, protocol, REMOVE);
+}
+
+
+static int
+iptablesOutputFixUdpChecksum(iptablesContext *ctx,
+                             const char *iface,
+                             int port,
+                             int action)
+{
+    char portstr[32];
+
+    snprintf(portstr, sizeof(portstr), "%d", port);
+    portstr[sizeof(portstr) - 1] = '\0';
+
+    return iptablesAddRemoveRule(ctx->mangle_postrouting,
+                                 AF_INET,
+                                 action,
+                                 "--out-interface", iface,
+                                 "--protocol", "udp",
+                                 "--destination-port", portstr,
+                                 "--jump", "CHECKSUM", "--checksum-fill",
+                                 NULL);
+}
+
+/**
+ * iptablesAddOutputFixUdpChecksum:
+ * @ctx: pointer to the IP table context
+ * @iface: the interface name
+ * @port: the UDP port to match
+ *
+ * Add a rule to the mangle table's POSTROUTING chain that fixes up the
+ * checksum of packets with the given destination @port.
+ * the given @iface interface for TCP packets.
+ *
+ * Returns 0 in case of success or an error code in case of error.
+ * (NB: if the system's iptables does not support checksum mangling,
+ * this will return an error, which should be ignored.)
+ */
+
+int
+iptablesAddOutputFixUdpChecksum(iptablesContext *ctx,
+                                const char *iface,
+                                int port)
+{
+    return iptablesOutputFixUdpChecksum(ctx, iface, port, ADD);
+}
+
+/**
+ * iptablesRemoveOutputFixUdpChecksum:
+ * @ctx: pointer to the IP table context
+ * @iface: the interface name
+ * @port: the UDP port of the rule to remove
+ *
+ * Removes the checksum fixup rule that was previous added with
+ * iptablesAddOutputFixUdpChecksum.
+ *
+ * Returns 0 in case of success or an error code in case of error
+ * (again, if iptables doesn't support checksum fixup, this will
+ * return an error, which should be ignored)
+ */
+int
+iptablesRemoveOutputFixUdpChecksum(iptablesContext *ctx,
+                                   const char *iface,
+                                   int port)
+{
+    return iptablesOutputFixUdpChecksum(ctx, iface, port, REMOVE);
+}
diff --git a/src/util/viriptables.h b/src/util/viriptables.h
new file mode 100644
index 0000000..e54f8b1
--- /dev/null
+++ b/src/util/viriptables.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2007, 2008 Red Hat, Inc.
+ *
+ * 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/>.
+ *
+ * Authors:
+ *     Mark McLoughlin <markmc at redhat.com>
+ */
+
+#ifndef __QEMUD_IPTABLES_H__
+# define __QEMUD_IPTABLES_H__
+
+# include "virsocketaddr.h"
+
+typedef struct _iptablesContext iptablesContext;
+
+iptablesContext *iptablesContextNew              (void);
+void             iptablesContextFree             (iptablesContext *ctx);
+
+int              iptablesAddTcpInput             (iptablesContext *ctx,
+                                                  int family,
+                                                  const char *iface,
+                                                  int port);
+int              iptablesRemoveTcpInput          (iptablesContext *ctx,
+                                                  int family,
+                                                  const char *iface,
+                                                  int port);
+
+int              iptablesAddUdpInput             (iptablesContext *ctx,
+                                                  int family,
+                                                  const char *iface,
+                                                  int port);
+int              iptablesRemoveUdpInput          (iptablesContext *ctx,
+                                                  int family,
+                                                  const char *iface,
+                                                  int port);
+
+int              iptablesAddForwardAllowOut      (iptablesContext *ctx,
+                                                  virSocketAddr *netaddr,
+                                                  unsigned int prefix,
+                                                  const char *iface,
+                                                  const char *physdev);
+int              iptablesRemoveForwardAllowOut   (iptablesContext *ctx,
+                                                  virSocketAddr *netaddr,
+                                                  unsigned int prefix,
+                                                  const char *iface,
+                                                  const char *physdev);
+
+int              iptablesAddForwardAllowRelatedIn(iptablesContext *ctx,
+                                                  virSocketAddr *netaddr,
+                                                  unsigned int prefix,
+                                                  const char *iface,
+                                                  const char *physdev);
+int              iptablesRemoveForwardAllowRelatedIn(iptablesContext *ctx,
+                                                  virSocketAddr *netaddr,
+                                                  unsigned int prefix,
+                                                  const char *iface,
+                                                  const char *physdev);
+
+int              iptablesAddForwardAllowIn       (iptablesContext *ctx,
+                                                  virSocketAddr *netaddr,
+                                                  unsigned int prefix,
+                                                  const char *iface,
+                                                  const char *physdev);
+int              iptablesRemoveForwardAllowIn    (iptablesContext *ctx,
+                                                  virSocketAddr *netaddr,
+                                                  unsigned int prefix,
+                                                  const char *iface,
+                                                  const char *physdev);
+
+int              iptablesAddForwardAllowCross    (iptablesContext *ctx,
+                                                  int family,
+                                                  const char *iface);
+int              iptablesRemoveForwardAllowCross (iptablesContext *ctx,
+                                                  int family,
+                                                  const char *iface);
+
+int              iptablesAddForwardRejectOut     (iptablesContext *ctx,
+                                                  int family,
+                                                  const char *iface);
+int              iptablesRemoveForwardRejectOut  (iptablesContext *ctx,
+                                                  int family,
+                                                  const char *iface);
+
+int              iptablesAddForwardRejectIn      (iptablesContext *ctx,
+                                                  int family,
+                                                  const char *iface);
+int              iptablesRemoveForwardRejectIn   (iptablesContext *ctx,
+                                                  int family,
+                                                  const char *iface);
+
+int              iptablesAddForwardMasquerade    (iptablesContext *ctx,
+                                                  virSocketAddr *netaddr,
+                                                  unsigned int prefix,
+                                                  const char *physdev,
+                                                  const char *protocol);
+int              iptablesRemoveForwardMasquerade (iptablesContext *ctx,
+                                                  virSocketAddr *netaddr,
+                                                  unsigned int prefix,
+                                                  const char *physdev,
+                                                  const char *protocol);
+int              iptablesAddOutputFixUdpChecksum (iptablesContext *ctx,
+                                                  const char *iface,
+                                                  int port);
+int              iptablesRemoveOutputFixUdpChecksum (iptablesContext *ctx,
+                                                     const char *iface,
+                                                     int port);
+
+#endif /* __QEMUD_IPTABLES_H__ */
-- 
1.7.11.7




More information about the libvir-list mailing list