From: "Daniel P. Berrange" <berrange(a)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(a)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(a)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(a)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(a)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