Add support for firewalld * 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 --- configure.ac | 9 ++++++ src/Makefile.am | 8 ++--- src/network/bridge_driver.c | 50 +++++++++++++++++++++++++++++ src/nwfilter/nwfilter_driver.c | 49 ++++++++++++++++++++++++++++ src/nwfilter/nwfilter_ebiptables_driver.c | 27 ++++++++++++++++ src/util/ebtables.c | 32 ++++++++++++++++++ src/util/iptables.c | 25 ++++++++++++--- 7 files changed, 192 insertions(+), 8 deletions(-) diff --git a/configure.ac b/configure.ac index 89fe818..41d9371 100644 --- a/configure.ac +++ b/configure.ac @@ -1191,6 +1191,15 @@ 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/src/Makefile.am b/src/Makefile.am index e48dfa5..e60a8af 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -941,9 +941,9 @@ noinst_LTLIBRARIES += libvirt_driver_network.la #libvirt_la_BUILT_LIBADD += libvirt_driver_network.la endif libvirt_driver_network_la_CFLAGS = \ - -I$(top_srcdir)/src/conf $(AM_CFLAGS) + -I$(top_srcdir)/src/conf $(AM_CFLAGS) $(DBUS_CFLAGS) if WITH_DRIVER_MODULES -libvirt_driver_network_la_LIBADD = ../gnulib/lib/libgnu.la +libvirt_driver_network_la_LIBADD = ../gnulib/lib/libgnu.la $(DBUS_LIBS) libvirt_driver_network_la_LDFLAGS = -module -avoid-version $(AM_LDFLAGS) endif libvirt_driver_network_la_SOURCES = $(NETWORK_DRIVER_SOURCES) @@ -1086,9 +1086,9 @@ libvirt_la_BUILT_LIBADD += libvirt_driver_nwfilter.la noinst_LTLIBRARIES += libvirt_driver_nwfilter.la endif libvirt_driver_nwfilter_la_CFLAGS = $(LIBPCAP_CFLAGS) \ - -I$(top_srcdir)/src/conf $(AM_CFLAGS) + -I$(top_srcdir)/src/conf $(AM_CFLAGS) $(DBUS_CFLAGS) libvirt_driver_nwfilter_la_LDFLAGS = $(LD_AMFLAGS) -libvirt_driver_nwfilter_la_LIBADD = $(LIBPCAP_LIBS) +libvirt_driver_nwfilter_la_LIBADD = $(LIBPCAP_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 d82212f..094bbae 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -63,6 +63,11 @@ #include "virnetdevbridge.h" #include "virnetdevtap.h" +#if HAVE_FIREWALLD +#include "virdbus.h" +#include "logging.h" +#endif + #define NETWORK_PID_DIR LOCALSTATEDIR "/run/libvirt/network" #define NETWORK_STATE_DIR LOCALSTATEDIR "/lib/libvirt/network" @@ -253,6 +258,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 = (struct network_driver *) 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: * @@ -262,6 +285,9 @@ static int networkStartup(int privileged) { uid_t uid = geteuid(); char *base = NULL; +#ifdef HAVE_FIREWALLD + DBusConnection *sysbus = NULL; +#endif if (VIR_ALLOC(driverState) < 0) goto error; @@ -326,6 +352,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, (void *)driverState, NULL); + } +#endif + return 0; out_of_memory: diff --git a/src/nwfilter/nwfilter_driver.c b/src/nwfilter/nwfilter_driver.c index ffb4b5d..da9f4a0 100644 --- a/src/nwfilter/nwfilter_driver.c +++ b/src/nwfilter/nwfilter_driver.c @@ -27,6 +27,11 @@ #include <config.h> +#if HAVE_FIREWALLD +#include "virdbus.h" +#include "logging.h" +#endif + #include "internal.h" #include "virterror_internal.h" @@ -47,6 +52,8 @@ static virNWFilterDriverStatePtr driverState; static int nwfilterDriverShutdown(void); +static int nwfilterDriverReload(void); + static void nwfilterDriverLock(virNWFilterDriverStatePtr driver) { virMutexLock(&driver->lock); @@ -57,6 +64,22 @@ static void nwfilterDriverUnlock(virNWFilterDriverStatePtr driver) } +#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: * @@ -66,6 +89,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 (virNWFilterLearnInit() < 0) return -1; diff --git a/src/nwfilter/nwfilter_ebiptables_driver.c b/src/nwfilter/nwfilter_ebiptables_driver.c index 8e4436f..0cd047a 100644 --- a/src/nwfilter/nwfilter_ebiptables_driver.c +++ b/src/nwfilter/nwfilter_ebiptables_driver.c @@ -4051,6 +4051,7 @@ ebiptablesDriverInit(bool privileged) { virBuffer buf = VIR_BUFFER_INITIALIZER; char *errmsg = NULL; + char *firewall_cmd_path = NULL; if (!privileged) return 0; @@ -4061,6 +4062,30 @@ 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; + virAsprintf(&ebtables_cmd_path, "%s --direct --passthrough eb", firewall_cmd_path); + virAsprintf(&iptables_cmd_path, "%s --direct --passthrough ipv4", firewall_cmd_path); + virAsprintf(&ip6tables_cmd_path, "%s --direct --passthrough ipv6", firewall_cmd_path); + } + 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); @@ -4099,6 +4124,8 @@ ebiptablesDriverInit(bool privileged) VIR_WARN("Could not find 'iptables' executable"); } + } + ip6tables_cmd_path = virFindFileInPath("ip6tables"); if (ip6tables_cmd_path) { NWFILTER_SET_IP6TABLES_SHELLVAR(&buf); diff --git a/src/util/ebtables.c b/src/util/ebtables.c index dcb3eb9..b7773ea 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,15 @@ 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; + argv[n++] = strdup("--direct"); + argv[n++] = strdup("--passthrough"); + argv[n++] = strdup("eb"); + } else +#endif if (!(argv[n++] = strdup(EBTABLES_PATH))) goto error; diff --git a/src/util/iptables.c b/src/util/iptables.c index 3023900..0cb3293 100644 --- a/src/util/iptables.c +++ b/src/util/iptables.c @@ -104,11 +104,28 @@ iptablesAddRemoveRule(iptRules *rules, int family, int action, { va_list args; int ret; - virCommandPtr cmd; + virCommandPtr cmd = NULL; const char *s; - - cmd = virCommandNew((family == AF_INET6) - ? IP6TABLES_PATH : IPTABLES_PATH); + 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); virCommandAddArgList(cmd, "--table", rules->table, action == ADD ? "--insert" : "--delete", -- 1.7.10 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list