* bridge_driver, nwfilter_driver: new dbus filters to get FirewallD1.Reloaded
signal and DBus.NameOwnerChanged on org.fedoraproject.FirewallD1
* iptables, ebtables, nwfilter_ebiptables_driver: use firewall-cmd direct
passthrough interface
* spec file changed as requested
---
configure.ac | 8 ++++++
libvirt.spec.in | 11 ++++++++
src/Makefile.am | 8 +++---
src/network/bridge_driver.c | 46 +++++++++++++++++++++++++++++++
src/nwfilter/nwfilter_driver.c | 46 +++++++++++++++++++++++++++++++
src/nwfilter/nwfilter_ebiptables_driver.c | 32 +++++++++++++++++++++
src/util/ebtables.c | 35 +++++++++++++++++++++++
src/util/iptables.c | 21 ++++++++++++--
8 files changed, 201 insertions(+), 6 deletions(-)
diff --git a/configure.ac b/configure.ac
index 8a04d91..7142450 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1282,6 +1282,14 @@ AM_CONDITIONAL([HAVE_POLKIT1], [test "x$with_polkit1" =
"xyes"])
AC_SUBST([POLKIT_CFLAGS])
AC_SUBST([POLKIT_LIBS])
+dnl firewalld
+AC_ARG_WITH([firewalld],
+ AC_HELP_STRING([--with-firewalld], [enable firewalld support]))
+if test "x$with_firewalld" = "xyes" ; then
+ AC_DEFINE_UNQUOTED([HAVE_FIREWALLD], [1], [whether firewalld support is enabled])
+fi
+AM_CONDITIONAL([HAVE_FIREWALLD], [test "x$with_firewalld" = "xyes"])
+
dnl Avahi library
AC_ARG_WITH([avahi],
AC_HELP_STRING([--with-avahi], [use avahi to advertise remote daemon
@<:@default=check@:>@]),
diff --git a/libvirt.spec.in b/libvirt.spec.in
index 67b955a..ea2fd88 100644
--- a/libvirt.spec.in
+++ b/libvirt.spec.in
@@ -106,6 +106,7 @@
%define with_sanlock 0%{!?_without_sanlock:0}
%define with_systemd 0%{!?_without_systemd:0}
%define with_numad 0%{!?_without_numad:0}
+%define with_firewalld 0%{!?_without_firewalld:0}
# Non-server/HV driver defaults which are always enabled
%define with_python 0%{!?_without_python:1}
@@ -146,6 +147,11 @@
%define with_systemd 1
%endif
+# Fedora 18 / RHEL-7 are first where firewalld support is enabled
+%if 0%{?fedora} >= 17 || 0%{?rhel} >= 7
+%define with_firewalld 1
+%endif
+
# RHEL-5 has restricted QEMU to x86_64 only and is too old for LXC
%if 0%{?rhel} == 5
%define with_qemu_tcg 0
@@ -1182,6 +1188,10 @@ of recent versions of Linux (and other OSes).
%define _without_driver_modules --without-driver-modules
%endif
+%if %{with_firewalld}
+%define _with_firewalld --with-firewalld
+%endif
+
%define when %(date +"%%F-%%T")
%define where %(hostname)
%define who %{?packager}%{!?packager:Unknown}
@@ -1240,6 +1250,7 @@ autoreconf -if
%{?_without_audit} \
%{?_without_dtrace} \
%{?_without_driver_modules} \
+ %{?_with_firewalld} \
%{with_packager} \
%{with_packager_version} \
--with-qemu-user=%{qemu_user} \
diff --git a/src/Makefile.am b/src/Makefile.am
index 6ed4a41..f3f4731 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -989,7 +989,7 @@ libvirt_driver_network_la_SOURCES =
libvirt_driver_network_la_LIBADD = libvirt_driver_network_impl.la
if WITH_DRIVER_MODULES
mod_LTLIBRARIES += libvirt_driver_network.la
-libvirt_driver_network_la_LIBADD += ../gnulib/lib/libgnu.la $(LIBNL_LIBS)
+libvirt_driver_network_la_LIBADD += ../gnulib/lib/libgnu.la $(LIBNL_LIBS) $(DBUS_LIBS)
libvirt_driver_network_la_LDFLAGS = -module -avoid-version $(AM_LDFLAGS)
else
noinst_LTLIBRARIES += libvirt_driver_network.la
@@ -999,7 +999,7 @@ endif
libvirt_driver_network_impl_la_CFLAGS = \
$(LIBNL_CFLAGS) \
- -I$(top_srcdir)/src/conf $(AM_CFLAGS)
+ -I$(top_srcdir)/src/conf $(AM_CFLAGS) $(DBUS_CFLAGS)
libvirt_driver_network_impl_la_SOURCES = $(NETWORK_DRIVER_SOURCES)
endif
EXTRA_DIST += network/default.xml
@@ -1149,9 +1149,9 @@ noinst_LTLIBRARIES += libvirt_driver_nwfilter.la
#libvirt_la_BUILT_LIBADD += libvirt_driver_nwfilter.la
endif
libvirt_driver_nwfilter_la_CFLAGS = $(LIBPCAP_CFLAGS) \
- -I$(top_srcdir)/src/conf $(LIBNL_CFLAGS) $(AM_CFLAGS)
+ -I$(top_srcdir)/src/conf $(LIBNL_CFLAGS) $(AM_CFLAGS) $(DBUS_CFLAGS)
libvirt_driver_nwfilter_la_LDFLAGS = $(LD_AMFLAGS)
-libvirt_driver_nwfilter_la_LIBADD = $(LIBPCAP_LIBS) $(LIBNL_LIBS)
+libvirt_driver_nwfilter_la_LIBADD = $(LIBPCAP_LIBS) $(LIBNL_LIBS) $(DBUS_LIBS)
if WITH_DRIVER_MODULES
libvirt_driver_nwfilter_la_LIBADD += ../gnulib/lib/libgnu.la
libvirt_driver_nwfilter_la_LDFLAGS += -module -avoid-version
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index a5046f1..86b178e 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -61,6 +61,7 @@
#include "virnetdev.h"
#include "virnetdevbridge.h"
#include "virnetdevtap.h"
+#include "virdbus.h"
#define NETWORK_PID_DIR LOCALSTATEDIR "/run/libvirt/network"
#define NETWORK_STATE_DIR LOCALSTATEDIR "/lib/libvirt/network"
@@ -248,6 +249,24 @@ networkAutostartConfigs(struct network_driver *driver) {
}
}
+#if HAVE_FIREWALLD
+static DBusHandlerResult
+firewalld_dbus_filter_bridge(DBusConnection *connection ATTRIBUTE_UNUSED, DBusMessage
*message, void *user_data) {
+ struct network_driver *_driverState = user_data;
+
+ if (dbus_message_is_signal(message, DBUS_INTERFACE_DBUS,
+ "NameOwnerChanged") ||
+ dbus_message_is_signal(message, "org.fedoraproject.FirewallD1",
+ "Reloaded"))
+ {
+ VIR_DEBUG("Reload in bridge_driver because of firewalld.");
+ networkReloadIptablesRules(_driverState);
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+#endif
+
/**
* networkStartup:
*
@@ -256,6 +275,9 @@ networkAutostartConfigs(struct network_driver *driver) {
static int
networkStartup(int privileged) {
char *base = NULL;
+#ifdef HAVE_FIREWALLD
+ DBusConnection *sysbus = NULL;
+#endif
if (VIR_ALLOC(driverState) < 0)
goto error;
@@ -322,6 +344,30 @@ networkStartup(int privileged) {
networkDriverUnlock(driverState);
+#ifdef HAVE_FIREWALLD
+ if (!(sysbus = virDBusGetSystemBus())) {
+ virErrorPtr err = virGetLastError();
+ VIR_WARN("DBus not available, disabling firewalld support in bridge_driver:
%s", err->message);
+ } else {
+ /* add matches for
+ * NameOwnerChanged on org.freedesktop.DBus for firewalld start/stop
+ * Reloaded on org.fedoraproject.FirewallD1 for firewalld reload
+ */
+ dbus_bus_add_match(sysbus,
+ "type='signal'"
+
",interface='"DBUS_INTERFACE_DBUS"'"
+ ",member='NameOwnerChanged'"
+ ",arg0='org.fedoraproject.FirewallD1'",
+ NULL);
+ dbus_bus_add_match(sysbus,
+ "type='signal'"
+ ",interface='org.fedoraproject.FirewallD1'"
+ ",member='Reloaded'",
+ NULL);
+ dbus_connection_add_filter(sysbus, firewalld_dbus_filter_bridge, driverState,
NULL);
+ }
+#endif
+
return 0;
out_of_memory:
diff --git a/src/nwfilter/nwfilter_driver.c b/src/nwfilter/nwfilter_driver.c
index 4fa73f8..09db599 100644
--- a/src/nwfilter/nwfilter_driver.c
+++ b/src/nwfilter/nwfilter_driver.c
@@ -27,6 +27,9 @@
#include <config.h>
+#include "virdbus.h"
+#include "logging.h"
+
#include "internal.h"
#include "virterror_internal.h"
@@ -49,6 +52,8 @@ static virNWFilterDriverStatePtr driverState;
static int nwfilterDriverShutdown(void);
+static int nwfilterDriverReload(void);
+
static void nwfilterDriverLock(virNWFilterDriverStatePtr driver)
{
virMutexLock(&driver->lock);
@@ -58,6 +63,21 @@ static void nwfilterDriverUnlock(virNWFilterDriverStatePtr driver)
virMutexUnlock(&driver->lock);
}
+#if HAVE_FIREWALLD
+static DBusHandlerResult
+firewalld_dbus_filter_nwfilter(DBusConnection *connection ATTRIBUTE_UNUSED, DBusMessage
*message, void *user_data ATTRIBUTE_UNUSED) {
+ if (dbus_message_is_signal(message, DBUS_INTERFACE_DBUS,
+ "NameOwnerChanged") ||
+ dbus_message_is_signal(message, "org.fedoraproject.FirewallD1",
+ "Reloaded"))
+ {
+ VIR_DEBUG("Reload in nwfilter_driver because of firewalld.");
+ nwfilterDriverReload();
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+#endif
/**
* virNWFilterStartup:
@@ -68,6 +88,32 @@ static int
nwfilterDriverStartup(int privileged) {
char *base = NULL;
+#ifdef HAVE_FIREWALLD
+ DBusConnection *sysbus = NULL;
+
+ if (!(sysbus = virDBusGetSystemBus())) {
+ virErrorPtr err = virGetLastError();
+ VIR_WARN("DBus not available, disabling firewalld support in
nwfilter_driver: %s", err->message);
+ } else {
+ /* add matches for
+ * NameOwnerChanged on org.freedesktop.DBus for firewalld start/stop
+ * Reloaded on org.fedoraproject.FirewallD1 for firewalld reload
+ */
+ dbus_bus_add_match(sysbus,
+ "type='signal'"
+
",interface='"DBUS_INTERFACE_DBUS"'"
+ ",member='NameOwnerChanged'"
+ ",arg0='org.fedoraproject.FirewallD1'",
+ NULL);
+ dbus_bus_add_match(sysbus,
+ "type='signal'"
+ ",interface='org.fedoraproject.FirewallD1'"
+ ",member='Reloaded'",
+ NULL);
+ dbus_connection_add_filter(sysbus, firewalld_dbus_filter_nwfilter, NULL, NULL);
+ }
+#endif
+
if (!privileged)
return 0;
diff --git a/src/nwfilter/nwfilter_ebiptables_driver.c
b/src/nwfilter/nwfilter_ebiptables_driver.c
index 6d6bc3b..6f3133f 100644
--- a/src/nwfilter/nwfilter_ebiptables_driver.c
+++ b/src/nwfilter/nwfilter_ebiptables_driver.c
@@ -4127,6 +4127,7 @@ ebiptablesDriverInit(bool privileged)
{
virBuffer buf = VIR_BUFFER_INITIALIZER;
char *errmsg = NULL;
+ char *firewall_cmd_path = NULL;
if (!privileged)
return 0;
@@ -4137,6 +4138,35 @@ ebiptablesDriverInit(bool privileged)
gawk_cmd_path = virFindFileInPath("gawk");
grep_cmd_path = virFindFileInPath("grep");
+ firewall_cmd_path = virFindFileInPath("firewall-cmd");
+ if (firewall_cmd_path) {
+ virBufferAsprintf(&buf, "IPT=%s\n", firewall_cmd_path);
+ /* basic probing */
+ virBufferAsprintf(&buf,
+ CMD_DEF("$IPT --state") CMD_SEPARATOR
+ CMD_EXEC
+ "%s",
+ CMD_STOPONERR(1));
+
+ if (ebiptablesExecCLI(&buf, NULL, NULL) >= 0) {
+ VIR_DEBUG("Using firewall-cmd in nwfilter_ebiptables_driver.");
+ ebtables_cmd_path = NULL;
+ iptables_cmd_path = NULL;
+ ip6tables_cmd_path = NULL;
+ ignore_value(virAsprintf(&ebtables_cmd_path, "%s --direct
--passthrough eb", firewall_cmd_path));
+ ignore_value(virAsprintf(&iptables_cmd_path, "%s --direct
--passthrough ipv4", firewall_cmd_path));
+ ignore_value(virAsprintf(&ip6tables_cmd_path, "%s --direct
--passthrough ipv6", firewall_cmd_path));
+ if (!ebtables_cmd_path || !iptables_cmd_path || !ip6tables_cmd_path) {
+ virReportOOMError();
+ return -1;
+ }
+
+ }
+ VIR_FREE(firewall_cmd_path);
+ }
+ if (ebtables_cmd_path == NULL || iptables_cmd_path == NULL ||
+ ip6tables_cmd_path == NULL) {
+
ebtables_cmd_path = virFindFileInPath("ebtables");
if (ebtables_cmd_path) {
NWFILTER_SET_EBTABLES_SHELLVAR(&buf);
@@ -4194,6 +4224,8 @@ ebiptablesDriverInit(bool privileged)
VIR_WARN("Could not find 'ip6tables' executable");
}
+ }
+
/* ip(6)tables support needs gawk & grep, ebtables doesn't */
if ((iptables_cmd_path != NULL || ip6tables_cmd_path != NULL) &&
(!grep_cmd_path || !gawk_cmd_path)) {
diff --git a/src/util/ebtables.c b/src/util/ebtables.c
index ca056b1..6f4d151 100644
--- a/src/util/ebtables.c
+++ b/src/util/ebtables.c
@@ -176,11 +176,34 @@ ebtablesAddRemoveRule(ebtRules *rules, int action, const char *arg,
...)
const char *s;
int n, command_idx;
+#if HAVE_FIREWALLD
+ int ret;
+ char *firewall_cmd_path = NULL;
+ virCommandPtr cmd = NULL;
+
+ firewall_cmd_path = virFindFileInPath("firewall-cmd");
+ if (firewall_cmd_path) {
+ cmd = virCommandNew(firewall_cmd_path);
+ virCommandAddArgList(cmd, "--state", NULL);
+ ret = virCommandRun(cmd, NULL);
+ if (ret != 0) {
+ VIR_FREE(firewall_cmd_path);
+ firewall_cmd_path = NULL;
+ }
+ virCommandFree(cmd);
+ }
+#endif
+
n = 1 + /* /sbin/ebtables */
2 + /* --table foo */
2 + /* --insert bar */
1; /* arg */
+#if HAVE_FIREWALLD
+ if (firewall_cmd_path)
+ n += 3; /* --direct --passthrough eb */
+#endif
+
va_start(args, arg);
while (va_arg(args, const char *))
n++;
@@ -192,6 +215,18 @@ ebtablesAddRemoveRule(ebtRules *rules, int action, const char *arg,
...)
n = 0;
+#if HAVE_FIREWALLD
+ if (firewall_cmd_path) {
+ if (!(argv[n++] = strdup(firewall_cmd_path)))
+ goto error;
+ if (!(argv[n++] = strdup("--direct")))
+ goto error;
+ if (!(argv[n++] = strdup("--passthrough")))
+ goto error;
+ if (!(argv[n++] = strdup("eb")))
+ goto error;
+ } else
+#endif
if (!(argv[n++] = strdup(EBTABLES_PATH)))
goto error;
diff --git a/src/util/iptables.c b/src/util/iptables.c
index b23aca9..7bad39d 100644
--- a/src/util/iptables.c
+++ b/src/util/iptables.c
@@ -101,9 +101,26 @@ iptablesAddRemoveRule(iptRules *rules, int family, int action,
{
va_list args;
int ret;
- virCommandPtr cmd;
+ virCommandPtr cmd = NULL;
const char *s;
-
+ char *firewall_cmd_path = NULL;
+
+#if HAVE_FIREWALLD
+ firewall_cmd_path = virFindFileInPath("firewall-cmd");
+ if (firewall_cmd_path) {
+ cmd = virCommandNew(firewall_cmd_path);
+ virCommandAddArgList(cmd, "--state", NULL);
+ ret = virCommandRun(cmd, NULL);
+ if (ret == 0) {
+ cmd = virCommandNew(firewall_cmd_path);
+ virCommandAddArgList(cmd, "--direct", "--passthrough",
+ (family == AF_INET6) ? "ipv6" :
"ipv4", NULL);
+ } else
+ cmd = NULL;
+ VIR_FREE(firewall_cmd_path);
+ }
+ if (!cmd)
+#endif
cmd = virCommandNew((family == AF_INET6)
? IP6TABLES_PATH : IPTABLES_PATH);
--
1.7.11.2