Change the nwfilter driver loading mechanism to read from nwfilter.conf.
By default, it will use the nftables driver, which follows the
firewall_backend bridge driver config logic.
Added nftables to *filter_tech_drivers as an available driver option
for users to choose from.
Signed-off-by: Dion Bosschieter <dionbosschieter@gmail.com>
---
po/POTFILES | 1 +
src/conf/virnwfilterobj.h | 20 --
src/nwfilter/libvirtd_nwfilter.aug | 37 ++++
src/nwfilter/meson.build | 37 ++++
src/nwfilter/nwfilter.conf.in | 26 +++
src/nwfilter/nwfilter_driver.c | 66 +++----
src/nwfilter/nwfilter_driver_conf.c | 210 +++++++++++++++++++++
src/nwfilter/nwfilter_driver_conf.h | 66 +++++++
src/nwfilter/nwfilter_ebiptables_driver.h | 2 +-
src/nwfilter/nwfilter_gentech_driver.c | 63 +++----
src/nwfilter/nwfilter_gentech_driver.h | 5 +-
src/nwfilter/nwfilter_tech_driver.c | 1 -
src/nwfilter/nwfilter_tech_driver.h | 1 +
src/nwfilter/test_libvirtd_nwfilter.aug.in | 5 +
14 files changed, 441 insertions(+), 99 deletions(-)
create mode 100644 src/nwfilter/libvirtd_nwfilter.aug
create mode 100644 src/nwfilter/nwfilter.conf.in
create mode 100644 src/nwfilter/nwfilter_driver_conf.c
create mode 100644 src/nwfilter/nwfilter_driver_conf.h
create mode 100644 src/nwfilter/test_libvirtd_nwfilter.aug.in
diff --git a/po/POTFILES b/po/POTFILES
index 51dae40cea..69cdba22f9 100644
--- a/po/POTFILES
+++ b/po/POTFILES
@@ -159,6 +159,7 @@ src/node_device/node_device_driver.c
src/node_device/node_device_udev.c
src/nwfilter/nwfilter_dhcpsnoop.c
src/nwfilter/nwfilter_driver.c
+src/nwfilter/nwfilter_driver_conf.c
src/nwfilter/nwfilter_ebiptables_driver.c
src/nwfilter/nwfilter_gentech_driver.c
src/nwfilter/nwfilter_learnipaddr.c
diff --git a/src/conf/virnwfilterobj.h b/src/conf/virnwfilterobj.h
index b67dc017c5..2c5df3e9ac 100644
--- a/src/conf/virnwfilterobj.h
+++ b/src/conf/virnwfilterobj.h
@@ -28,26 +28,6 @@ typedef struct _virNWFilterObj virNWFilterObj;
typedef struct _virNWFilterObjList virNWFilterObjList;
-typedef struct _virNWFilterDriverState virNWFilterDriverState;
-struct _virNWFilterDriverState {
- bool privileged;
-
- /* pid file FD, ensures two copies of the driver can't use the same root */
- int lockFD;
-
- virNWFilterObjList *nwfilters;
-
- virNWFilterBindingObjList *bindings;
-
- char *stateDir;
- char *configDir;
- char *bindingDir;
-
- /* Recursive. Hold for filter changes, instantiation or deletion */
- virMutex updateLock;
- bool updateLockInitialized;
-};
-
virNWFilterDef *
virNWFilterObjGetDef(virNWFilterObj *obj);
diff --git a/src/nwfilter/libvirtd_nwfilter.aug b/src/nwfilter/libvirtd_nwfilter.aug
new file mode 100644
index 0000000000..96351d272a
--- /dev/null
+++ b/src/nwfilter/libvirtd_nwfilter.aug
@@ -0,0 +1,37 @@
+(* /etc/libvirt/nwfilter.conf *)
+
+module Libvirtd_nwfilter =
+ autoload xfm
+
+ let eol = del /[ \t]*\n/ "\n"
+ let value_sep = del /[ \t]*=[ \t]*/ " = "
+ let indent = del /[ \t]*/ ""
+
+ let array_sep = del /,[ \t\n]*/ ", "
+ let array_start = del /\[[ \t\n]*/ "[ "
+ let array_end = del /\]/ "]"
+
+ let str_val = del /\"/ "\"" . store /[^\"]*/ . del /\"/ "\""
+ let bool_val = store /0|1/
+ let int_val = store /[0-9]+/
+ let str_array_element = [ seq "el" . str_val ] . del /[ \t\n]*/ ""
+ let str_array_val = counter "el" . array_start . ( str_array_element . ( array_sep . str_array_element ) * ) ? . array_end
+
+ let str_entry (kw:string) = [ key kw . value_sep . str_val ]
+ let bool_entry (kw:string) = [ key kw . value_sep . bool_val ]
+ let int_entry (kw:string) = [ key kw . value_sep . int_val ]
+ let str_array_entry (kw:string) = [ key kw . value_sep . str_array_val ]
+
+ (* Each entry in the config is one of the following *)
+ let entry = str_entry "nwfilter_driver"
+ let comment = [ label "#comment" . del /#[ \t]*/ "# " . store /([^ \t\n][^\n]*)?/ . del /\n/ "\n" ]
+ let empty = [ label "#empty" . eol ]
+
+ let record = indent . entry . eol
+
+ let lns = ( record | comment | empty ) *
+
+ let filter = incl "/etc/libvirt/nwfilter.conf"
+ . Util.stdexcl
+
+ let xfm = transform lns filter
diff --git a/src/nwfilter/meson.build b/src/nwfilter/meson.build
index a94d72d570..4d8abc7deb 100644
--- a/src/nwfilter/meson.build
+++ b/src/nwfilter/meson.build
@@ -1,5 +1,6 @@
nwfilter_driver_sources = [
'nwfilter_driver.c',
+ 'nwfilter_driver_conf.c',
'nwfilter_gentech_driver.c',
'nwfilter_tech_driver.c',
'nwfilter_dhcpsnoop.c',
@@ -46,6 +47,42 @@ if conf.has('WITH_NWFILTER')
],
}
+ nwfilter_options_conf = configuration_data({
+ 'FIREWALL_BACKEND_PRIORITY': ', '.join(firewall_backend_priority),
+ 'FIREWALL_BACKEND': firewall_backend_priority[0],
+ })
+
+ nwfilter_conf = configure_file(
+ input: 'nwfilter.conf.in',
+ output: 'nwfilter.conf',
+ configuration: nwfilter_options_conf,
+ )
+
+ nwfilter_options_hack_conf = configuration_data({
+ 'FIREWALL_BACKEND_PRIORITY': ', '.join(firewall_backend_priority),
+ 'FIREWALL_BACKEND': firewall_backend_priority[0],
+ # This hack is necessary because the output file is going to be
+ # used as input for another configure_file() call later, which
+ # will take care of substituting @CONFIG@ with useful data
+ 'CONFIG': '@CONFIG@',
+ })
+ test_libvirtd_network_aug_tmp = configure_file(
+ input: 'test_libvirtd_nwfilter.aug.in',
+ output: 'test_libvirtd_nwfilter.aug.tmp',
+ configuration: nwfilter_options_hack_conf,
+ )
+
+ virt_conf_files += nwfilter_conf
+ virt_aug_files += files('libvirtd_nwfilter.aug')
+ virt_test_aug_files += {
+ 'name': 'test_libvirtd_nwfilter.aug',
+ 'aug': test_libvirtd_network_aug_tmp,
+ 'conf': nwfilter_conf,
+ 'test_name': 'libvirtd_nwfilter',
+ 'test_srcdir': meson.current_source_dir(),
+ 'test_builddir': meson.current_build_dir(),
+ }
+
virt_daemon_confs += {
'name': 'virtnwfilterd',
}
diff --git a/src/nwfilter/nwfilter.conf.in b/src/nwfilter/nwfilter.conf.in
new file mode 100644
index 0000000000..8ed5cbaa53
--- /dev/null
+++ b/src/nwfilter/nwfilter.conf.in
@@ -0,0 +1,26 @@
+# Master configuration file for the nwfilter driver.
+# All settings described here are optional - if omitted, sensible
+# defaults are used.
+
+# nwfilter_driver:
+#
+# determines which driver to use to setup nwfilter firewall rules
+#
+# Supported settings:
+#
+# iptables - use ebtables and iptables commands to construct the user
+# defined firewall
+# nftables - use nft commands to construct the user defined firewall
+#
+# If nwfilter_driver isn't configured, libvirt will choose the
+# first available backend from the following list:
+#
+# [@FIREWALL_BACKEND_PRIORITY@]
+#
+# (NB: switching from one backend to another while there are active
+# virtual networks *isn't* supported. The change will take place the
+# next time that libvirtd/virtnetworkd is restarted - all existing
+# firewalls remain, and have to be cleaned up manually
+# reloaded using the new backend.)
+#
+#nwfilter_driver = "@FIREWALL_BACKEND@"
diff --git a/src/nwfilter/nwfilter_driver.c b/src/nwfilter/nwfilter_driver.c
index 522cfda022..6b1100b675 100644
--- a/src/nwfilter/nwfilter_driver.c
+++ b/src/nwfilter/nwfilter_driver.c
@@ -26,17 +26,15 @@
#include "virgdbus.h"
#include "virlog.h"
-
#include "internal.h"
-
#include "virerror.h"
#include "datatypes.h"
#include "nwfilter_driver.h"
+#include "nwfilter_driver_conf.h"
#include "nwfilter_gentech_driver.h"
#include "configmake.h"
#include "virpidfile.h"
#include "viraccessapicheck.h"
-
#include "nwfilter_ipaddrmap.h"
#include "nwfilter_dhcpsnoop.h"
#include "nwfilter_learnipaddr.h"
@@ -159,9 +157,12 @@ virNWFilterTriggerRebuildImpl(void *opaque)
static int
nwfilterStateCleanupLocked(void)
{
+ g_autoptr(virNWFilterDriverConfig) cfg = NULL;
if (!driver)
return -1;
+ cfg = virNWFilterDriverGetConfig(driver);
+
if (driver->privileged) {
virNWFilterConfLayerShutdown();
virNWFilterDHCPSnoopShutdown();
@@ -171,11 +172,7 @@ nwfilterStateCleanupLocked(void)
nwfilterDriverRemoveDBusMatches();
if (driver->lockFD != -1)
- virPidFileRelease(driver->stateDir, "driver", driver->lockFD);
-
- g_free(driver->stateDir);
- g_free(driver->configDir);
- g_free(driver->bindingDir);
+ virPidFileRelease(cfg->stateDir, "driver", driver->lockFD);
}
virObjectUnref(driver->bindings);
@@ -216,6 +213,7 @@ nwfilterStateInitialize(bool privileged,
void *opaque G_GNUC_UNUSED)
{
VIR_LOCK_GUARD lock = virLockGuardLock(&driverMutex);
+ virNWFilterDriverConfig *cfg;
GDBusConnection *sysbus = NULL;
if (root != NULL) {
@@ -236,6 +234,9 @@ nwfilterStateInitialize(bool privileged,
driver->updateLockInitialized = true;
driver->privileged = privileged;
+ if (!(driver->config = cfg = virNWFilterDriverConfigNew(privileged)))
+ goto error;
+
if (!(driver->nwfilters = virNWFilterObjListNew()))
goto error;
@@ -245,16 +246,8 @@ nwfilterStateInitialize(bool privileged,
if (!privileged)
return VIR_DRV_STATE_INIT_SKIPPED;
- driver->stateDir = g_strdup(RUNSTATEDIR "/libvirt/nwfilter");
-
- if (g_mkdir_with_parents(driver->stateDir, S_IRWXU) < 0) {
- virReportSystemError(errno, _("cannot create state directory '%1$s'"),
- driver->stateDir);
- goto error;
- }
-
if ((driver->lockFD =
- virPidFileAcquire(driver->stateDir, "driver", getpid())) < 0)
+ virPidFileAcquire(cfg->stateDir, "driver", getpid())) < 0)
goto error;
if (virNWFilterIPAddrMapInit() < 0)
@@ -266,7 +259,7 @@ nwfilterStateInitialize(bool privileged,
if (virNWFilterDHCPSnoopInit() < 0)
goto error;
- if (virNWFilterTechDriversInit(privileged) < 0)
+ if (virNWFilterTechDriversInit(privileged, cfg->firewallBackend) < 0)
goto error;
if (virNWFilterConfLayerInit(virNWFilterTriggerRebuildImpl, driver) < 0)
@@ -279,26 +272,10 @@ nwfilterStateInitialize(bool privileged,
if (sysbus)
nwfilterDriverInstallDBusMatches(sysbus);
- driver->configDir = g_strdup(SYSCONFDIR "/libvirt/nwfilter");
-
- if (g_mkdir_with_parents(driver->configDir, S_IRWXU) < 0) {
- virReportSystemError(errno, _("cannot create config directory '%1$s'"),
- driver->configDir);
- goto error;
- }
-
- driver->bindingDir = g_strdup(RUNSTATEDIR "/libvirt/nwfilter-binding");
-
- if (g_mkdir_with_parents(driver->bindingDir, S_IRWXU) < 0) {
- virReportSystemError(errno, _("cannot create config directory '%1$s'"),
- driver->bindingDir);
+ if (virNWFilterObjListLoadAllConfigs(driver->nwfilters, cfg->configDir) < 0)
goto error;
- }
- if (virNWFilterObjListLoadAllConfigs(driver->nwfilters, driver->configDir) < 0)
- goto error;
-
- if (virNWFilterBindingObjListLoadAllConfigs(driver->bindings, driver->bindingDir) < 0)
+ if (virNWFilterBindingObjListLoadAllConfigs(driver->bindings, cfg->bindingDir) < 0)
goto error;
if (virNWFilterBuildAll(driver, false) < 0)
@@ -320,19 +297,22 @@ nwfilterStateInitialize(bool privileged,
static int
nwfilterStateReload(void)
{
+ g_autoptr(virNWFilterDriverConfig) cfg = NULL;
if (!driver)
return -1;
if (!driver->privileged)
return 0;
+ cfg = virNWFilterDriverGetConfig(driver);
+
virNWFilterDHCPSnoopEnd(NULL);
/* shut down all threads -- they will be restarted if necessary */
virNWFilterLearnThreadsTerminate(true);
VIR_WITH_MUTEX_LOCK_GUARD(&driverMutex) {
VIR_WITH_MUTEX_LOCK_GUARD(&driver->updateLock) {
- virNWFilterObjListLoadAllConfigs(driver->nwfilters, driver->configDir);
+ virNWFilterObjListLoadAllConfigs(driver->nwfilters, cfg->configDir);
}
@@ -535,6 +515,7 @@ nwfilterDefineXMLFlags(virConnectPtr conn,
virNWFilterObj *obj = NULL;
virNWFilterDef *objdef;
virNWFilterPtr nwfilter = NULL;
+ g_autoptr(virNWFilterDriverConfig) cfg = virNWFilterDriverGetConfig(driver);
virCheckFlags(VIR_NWFILTER_DEFINE_VALIDATE, NULL);
@@ -558,7 +539,7 @@ nwfilterDefineXMLFlags(virConnectPtr conn,
def = NULL;
objdef = virNWFilterObjGetDef(obj);
- if (virNWFilterSaveConfig(driver->configDir, objdef) < 0) {
+ if (virNWFilterSaveConfig(cfg->configDir, objdef) < 0) {
virNWFilterObjListRemove(driver->nwfilters, obj);
goto cleanup;
}
@@ -588,6 +569,7 @@ nwfilterUndefine(virNWFilterPtr nwfilter)
virNWFilterObj *obj;
virNWFilterDef *def;
int ret = -1;
+ g_autoptr(virNWFilterDriverConfig) cfg = virNWFilterDriverGetConfig(driver);
VIR_WITH_MUTEX_LOCK_GUARD(&driver->updateLock) {
if (!(obj = nwfilterObjFromNWFilter(nwfilter->uuid)))
@@ -604,7 +586,7 @@ nwfilterUndefine(virNWFilterPtr nwfilter)
goto cleanup;
}
- if (virNWFilterDeleteDef(driver->configDir, def) < 0)
+ if (virNWFilterDeleteDef(cfg->configDir, def) < 0)
goto cleanup;
virNWFilterObjListRemove(driver->nwfilters, obj);
@@ -730,6 +712,7 @@ nwfilterBindingCreateXML(virConnectPtr conn,
virNWFilterBindingDef *def;
virNWFilterBindingObj *obj = NULL;
virNWFilterBindingPtr ret = NULL;
+ g_autoptr(virNWFilterDriverConfig) cfg = virNWFilterDriverGetConfig(driver);
virCheckFlags(VIR_NWFILTER_BINDING_CREATE_VALIDATE, NULL);
@@ -772,7 +755,7 @@ nwfilterBindingCreateXML(virConnectPtr conn,
}
}
- virNWFilterBindingObjSave(obj, driver->bindingDir);
+ virNWFilterBindingObjSave(obj, cfg->bindingDir);
cleanup:
if (!obj)
@@ -799,6 +782,7 @@ nwfilterBindingDelete(virNWFilterBindingPtr binding)
virNWFilterBindingObj *obj;
virNWFilterBindingDef *def;
int ret = -1;
+ g_autoptr(virNWFilterDriverConfig) cfg = virNWFilterDriverGetConfig(driver);
obj = virNWFilterBindingObjListFindByPortDev(driver->bindings, binding->portdev);
if (!obj) {
@@ -814,7 +798,7 @@ nwfilterBindingDelete(virNWFilterBindingPtr binding)
VIR_WITH_MUTEX_LOCK_GUARD(&driver->updateLock) {
virNWFilterTeardownFilter(def);
}
- virNWFilterBindingObjDelete(obj, driver->bindingDir);
+ virNWFilterBindingObjDelete(obj, cfg->bindingDir);
virNWFilterBindingObjListRemove(driver->bindings, obj);
ret = 0;
diff --git a/src/nwfilter/nwfilter_driver_conf.c b/src/nwfilter/nwfilter_driver_conf.c
new file mode 100644
index 0000000000..238e6771f5
--- /dev/null
+++ b/src/nwfilter/nwfilter_driver_conf.c
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2022 Red Hat, Inc.
+ *
+ * nwfilter_driver_conf.c: nwfilter.conf config file inspection
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <config.h>
+#include "configmake.h"
+#include "datatypes.h"
+#include "virlog.h"
+#include "virerror.h"
+#include "virfile.h"
+#include "virutil.h"
+#include "virfirewall.h" /* for binary names */
+#include "nwfilter_driver_conf.h"
+
+
+#define VIR_FROM_THIS VIR_FROM_NWFILTER
+
+VIR_LOG_INIT("nwfilter.nwfilter_driver");
+
+static virClass *virNWFilterDriverConfigClass;
+static void virNWFilterDriverConfigDispose(void *obj);
+
+static int
+virNWFilterConfigOnceInit(void)
+{
+ if (!VIR_CLASS_NEW(virNWFilterDriverConfig, virClassForObject()))
+ return -1;
+
+ return 0;
+}
+
+
+VIR_ONCE_GLOBAL_INIT(virNWFilterConfig);
+
+
+static int
+virNWFilterLoadDriverConfig(virNWFilterDriverConfig *cfg,
+ const char *filename)
+{
+ g_autoptr(virConf) conf = NULL;
+ g_autofree char *fwBackendStr = NULL;
+ bool fwBackendSelected = false;
+ size_t i;
+ int fwBackends[] = {
+ FIREWALL_BACKENDS
+ };
+ G_STATIC_ASSERT(G_N_ELEMENTS(fwBackends) > 0 &&
+ G_N_ELEMENTS(fwBackends) <= VIR_FIREWALL_BACKEND_LAST);
+ int nFwBackends = G_N_ELEMENTS(fwBackends);
+
+ if (access(filename, R_OK) == 0) {
+
+ conf = virConfReadFile(filename, 0);
+ if (!conf)
+ return -1;
+
+ /* use virConfGetValue*(conf, ...) functions to read any settings into cfg */
+
+ if (virConfGetValueString(conf, "nwfilter_driver", &fwBackendStr) < 0)
+ return -1;
+
+ if (fwBackendStr) {
+ fwBackends[0] = virFirewallBackendTypeFromString(fwBackendStr);
+ nFwBackends = 1;
+
+ if (fwBackends[0] < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("unrecognized nwfilter_driver = '%1$s' set in nwfilter driver config file %2$s"),
+ fwBackendStr, filename);
+ return -1;
+ }
+ VIR_DEBUG("nwfilter_driver setting requested from config file %s: '%s'",
+ filename, virFirewallBackendTypeToString(fwBackends[0]));
+ }
+ }
+
+ for (i = 0; i < nFwBackends && !fwBackendSelected; i++) {
+ switch ((virFirewallBackend)fwBackends[i]) {
+ case VIR_FIREWALL_BACKEND_NONE:
+ fwBackendSelected = true;
+ break;
+
+ case VIR_FIREWALL_BACKEND_IPTABLES: {
+ g_autofree char *iptablesInPath = virFindFileInPath(IPTABLES);
+
+ if (iptablesInPath)
+ fwBackendSelected = true;
+ break;
+ }
+
+ case VIR_FIREWALL_BACKEND_NFTABLES: {
+ g_autofree char *nftablesInPath = virFindFileInPath(NFT);
+
+ if (nftablesInPath)
+ fwBackendSelected = true;
+ break;
+ }
+
+ case VIR_FIREWALL_BACKEND_PF: {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("unsupported nwfilter driver PF"));
+ return -1;
+ }
+
+ case VIR_FIREWALL_BACKEND_LAST:
+ virReportEnumRangeError(virFirewallBackend, fwBackends[i]);
+ return -1;
+ }
+
+ if (fwBackendSelected)
+ cfg->firewallBackend = fwBackends[i];
+ }
+
+ if (fwBackendSelected) {
+ VIR_INFO("using nwfilter_driver: '%s'",
+ virFirewallBackendTypeToString(cfg->firewallBackend));
+ return 0;
+ } else if (fwBackendStr) {
+ /* the explicitly requested driver wasn't found - this is a failure */
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("requested nwfilter_driver '%1$s' is not available"),
+ fwBackendStr);
+ return -1;
+ } else {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("could not find a usable nwfilter driver"));
+ return -1;
+ }
+}
+
+
+virNWFilterDriverConfig *
+virNWFilterDriverConfigNew(bool privileged)
+{
+ g_autoptr(virNWFilterDriverConfig) cfg = NULL;
+ g_autofree char *configdir = NULL;
+ g_autofree char *configfile = NULL;
+
+ if (virNWFilterConfigInitialize() < 0)
+ return NULL;
+
+ if (!(cfg = virObjectNew(virNWFilterDriverConfigClass)))
+ return NULL;
+
+ if (!privileged)
+ return g_steal_pointer(&cfg);
+
+ cfg->stateDir = g_strdup(RUNSTATEDIR "/libvirt/nwfilter");
+ cfg->configDir = g_strdup(SYSCONFDIR "/libvirt/nwfilter");
+ cfg->bindingDir = g_strdup(RUNSTATEDIR "/libvirt/nwfilter-binding");
+ configfile = g_strdup(SYSCONFDIR "/libvirt/nwfilter.conf");
+
+ if (virNWFilterLoadDriverConfig(cfg, configfile) < 0)
+ return NULL;
+
+ if (g_mkdir_with_parents(cfg->stateDir, S_IRWXU) < 0) {
+ virReportSystemError(errno, _("cannot create state directory '%1$s'"),
+ cfg->stateDir);
+ return NULL;
+ }
+
+ if (g_mkdir_with_parents(cfg->configDir, S_IRWXU) < 0) {
+ virReportSystemError(errno, _("cannot create config directory '%1$s'"),
+ cfg->configDir);
+ return NULL;
+ }
+
+ if (g_mkdir_with_parents(cfg->bindingDir, S_IRWXU) < 0) {
+ virReportSystemError(errno, _("cannot create config directory '%1$s'"),
+ cfg->bindingDir);
+ return NULL;
+ }
+
+ return g_steal_pointer(&cfg);
+}
+
+
+virNWFilterDriverConfig *
+virNWFilterDriverGetConfig(virNWFilterDriverState *driver)
+{
+ return virObjectRef(driver->config);
+}
+
+
+static void
+virNWFilterDriverConfigDispose(void *obj)
+{
+ virNWFilterDriverConfig *cfg = obj;
+
+ g_free(cfg->stateDir);
+ g_free(cfg->configDir);
+ g_free(cfg->bindingDir);
+}
diff --git a/src/nwfilter/nwfilter_driver_conf.h b/src/nwfilter/nwfilter_driver_conf.h
new file mode 100644
index 0000000000..e017149663
--- /dev/null
+++ b/src/nwfilter/nwfilter_driver_conf.h
@@ -0,0 +1,66 @@
+/*
+ * nwfilter_driver_conf.h: nwfilter driver state and config objects
+ *
+ * Copyright (C) 2006-2013 Red Hat, Inc.
+ * Copyright (C) 2006 Daniel P. Berrange
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "libvirt_internal.h"
+#include "virthread.h"
+#include "virnwfilterobj.h"
+#include "virfirewall.h"
+#include "virinhibitor.h"
+
+typedef struct _virNWFilterDriverConfig virNWFilterDriverConfig;
+struct _virNWFilterDriverConfig {
+ virObject parent;
+
+ /* Immutable pointers, Immutable objects */
+ char *stateDir;
+ char *configDir;
+ char *bindingDir;
+
+ virFirewallBackend firewallBackend;
+};
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(virNWFilterDriverConfig, virObjectUnref);
+
+/* Main driver state */
+typedef struct _virNWFilterDriverState virNWFilterDriverState;
+struct _virNWFilterDriverState {
+ bool privileged;
+
+ /* pid file FD, ensures two copies of the driver can't use the same root */
+ int lockFD;
+
+ virNWFilterObjList *nwfilters;
+
+ virNWFilterBindingObjList *bindings;
+
+ virNWFilterDriverConfig *config;
+
+ /* Recursive. Hold for filter changes, instantiation or deletion */
+ virMutex updateLock;
+ bool updateLockInitialized;
+};
+
+virNWFilterDriverConfig *
+virNWFilterDriverConfigNew(bool privileged);
+virNWFilterDriverConfig *
+virNWFilterDriverGetConfig(virNWFilterDriverState *driver);
diff --git a/src/nwfilter/nwfilter_ebiptables_driver.h b/src/nwfilter/nwfilter_ebiptables_driver.h
index cb146f9f97..dfaea5af3d 100644
--- a/src/nwfilter/nwfilter_ebiptables_driver.h
+++ b/src/nwfilter/nwfilter_ebiptables_driver.h
@@ -27,6 +27,6 @@
extern virNWFilterTechDriver ebiptables_driver;
-#define EBIPTABLES_DRIVER_ID "ebiptables"
+#define EBIPTABLES_DRIVER_ID "iptables"
#define IPTABLES_MAX_COMMENT_LENGTH 256
diff --git a/src/nwfilter/nwfilter_gentech_driver.c b/src/nwfilter/nwfilter_gentech_driver.c
index 1465734a54..fdba2393f9 100644
--- a/src/nwfilter/nwfilter_gentech_driver.c
+++ b/src/nwfilter/nwfilter_gentech_driver.c
@@ -32,6 +32,7 @@
#include "nwfilter_dhcpsnoop.h"
#include "nwfilter_ipaddrmap.h"
#include "nwfilter_learnipaddr.h"
+#include "nwfilter_nftables_driver.h"
#include "virnetdev.h"
#define VIR_FROM_THIS VIR_FROM_NWFILTER
@@ -48,18 +49,23 @@ static int _virNWFilterTeardownFilter(const char *ifname);
static virNWFilterTechDriver *filter_tech_drivers[] = {
&ebiptables_driver,
- NULL
+ &nftables_driver,
};
-int virNWFilterTechDriversInit(bool privileged)
+int virNWFilterTechDriversInit(bool privileged, virFirewallBackend firewallBackend)
{
size_t i = 0;
- VIR_DEBUG("Initializing NWFilter technology drivers");
- while (filter_tech_drivers[i]) {
- if (!(filter_tech_drivers[i]->flags & TECHDRV_FLAG_INITIALIZED))
+ VIR_DEBUG("Initializing NWFilter technology drivers, chosen '%s'",
+ virFirewallBackendTypeToString(firewallBackend));
+
+ for (i = 0; i < G_N_ELEMENTS(filter_tech_drivers); i++) {
+ if (filter_tech_drivers[i]->flags & TECHDRV_FLAG_INITIALIZED)
+ continue;
+ if (STREQ(filter_tech_drivers[i]->name,
+ virFirewallBackendTypeToString(firewallBackend)))
filter_tech_drivers[i]->init(privileged);
- i++;
}
+
return 0;
}
@@ -67,25 +73,20 @@ int virNWFilterTechDriversInit(bool privileged)
void virNWFilterTechDriversShutdown(void)
{
size_t i = 0;
- while (filter_tech_drivers[i]) {
+ for (i = 0; i < G_N_ELEMENTS(filter_tech_drivers); i++) {
if ((filter_tech_drivers[i]->flags & TECHDRV_FLAG_INITIALIZED))
filter_tech_drivers[i]->shutdown();
- i++;
}
}
static virNWFilterTechDriver *
-virNWFilterTechDriverForName(const char *name)
+virNWFilterInitializedTechDriver(void)
{
size_t i = 0;
- while (filter_tech_drivers[i]) {
- if (STREQ(filter_tech_drivers[i]->name, name)) {
- if ((filter_tech_drivers[i]->flags & TECHDRV_FLAG_INITIALIZED) == 0)
- break;
+ for (i = 0; i < G_N_ELEMENTS(filter_tech_drivers); i++) {
+ if ((filter_tech_drivers[i]->flags & TECHDRV_FLAG_INITIALIZED))
return filter_tech_drivers[i];
- }
- i++;
}
return NULL;
}
@@ -617,7 +618,6 @@ virNWFilterInstantiateFilterUpdate(virNWFilterDriverState *driver,
bool *foundNewFilter)
{
int rc = -1;
- const char *drvname = EBIPTABLES_DRIVER_ID;
virNWFilterTechDriver *techdriver;
virNWFilterObj *obj;
virNWFilterDef *filter;
@@ -625,12 +625,11 @@ virNWFilterInstantiateFilterUpdate(virNWFilterDriverState *driver,
char vmmacaddr[VIR_MAC_STRING_BUFLEN] = {0};
virNWFilterVarValue *ipaddr;
- techdriver = virNWFilterTechDriverForName(drvname);
+ techdriver = virNWFilterInitializedTechDriver();
if (!techdriver) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Could not get access to ACL tech driver '%1$s'"),
- drvname);
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not get access to ACL tech driver"));
return -1;
}
@@ -768,15 +767,13 @@ virNWFilterUpdateInstantiateFilter(virNWFilterDriverState *driver,
static int
virNWFilterRollbackUpdateFilter(virNWFilterBindingDef *binding)
{
- const char *drvname = EBIPTABLES_DRIVER_ID;
int ifindex;
virNWFilterTechDriver *techdriver;
- techdriver = virNWFilterTechDriverForName(drvname);
+ techdriver = virNWFilterInitializedTechDriver();
if (!techdriver) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Could not get access to ACL tech driver '%1$s'"),
- drvname);
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not get access to ACL tech driver"));
return -1;
}
@@ -793,15 +790,13 @@ virNWFilterRollbackUpdateFilter(virNWFilterBindingDef *binding)
static int
virNWFilterTearOldFilter(virNWFilterBindingDef *binding)
{
- const char *drvname = EBIPTABLES_DRIVER_ID;
int ifindex;
virNWFilterTechDriver *techdriver;
- techdriver = virNWFilterTechDriverForName(drvname);
+ techdriver = virNWFilterInitializedTechDriver();
if (!techdriver) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Could not get access to ACL tech driver '%1$s'"),
- drvname);
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not get access to ACL tech driver"));
return -1;
}
@@ -818,14 +813,12 @@ virNWFilterTearOldFilter(virNWFilterBindingDef *binding)
static int
_virNWFilterTeardownFilter(const char *ifname)
{
- const char *drvname = EBIPTABLES_DRIVER_ID;
virNWFilterTechDriver *techdriver;
- techdriver = virNWFilterTechDriverForName(drvname);
+ techdriver = virNWFilterInitializedTechDriver();
if (!techdriver) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Could not get access to ACL tech driver '%1$s'"),
- drvname);
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not get access to ACL tech driver"));
return -1;
}
diff --git a/src/nwfilter/nwfilter_gentech_driver.h b/src/nwfilter/nwfilter_gentech_driver.h
index 946d5d3d56..59d76b852c 100644
--- a/src/nwfilter/nwfilter_gentech_driver.h
+++ b/src/nwfilter/nwfilter_gentech_driver.h
@@ -24,8 +24,11 @@
#include "virnwfilterobj.h"
#include "virnwfilterbindingdef.h"
+#include "nwfilter_driver_conf.h"
+#include "virfirewall.h"
-int virNWFilterTechDriversInit(bool privileged);
+
+int virNWFilterTechDriversInit(bool privileged, virFirewallBackend firewallBackend);
void virNWFilterTechDriversShutdown(void);
enum instCase {
diff --git a/src/nwfilter/nwfilter_tech_driver.c b/src/nwfilter/nwfilter_tech_driver.c
index 7b3edff8e6..ece8f90bf8 100644
--- a/src/nwfilter/nwfilter_tech_driver.c
+++ b/src/nwfilter/nwfilter_tech_driver.c
@@ -19,7 +19,6 @@
#include <config.h>
#include "nwfilter_tech_driver.h"
-#include "nwfilter_conf.h"
#define VIR_FROM_THIS VIR_FROM_NWFILTER
diff --git a/src/nwfilter/nwfilter_tech_driver.h b/src/nwfilter/nwfilter_tech_driver.h
index 7a85c46339..103f33a3b8 100644
--- a/src/nwfilter/nwfilter_tech_driver.h
+++ b/src/nwfilter/nwfilter_tech_driver.h
@@ -25,6 +25,7 @@
#include "virnwfilterobj.h"
#include "virstring.h"
+#include "nwfilter_driver_conf.h"
typedef struct _virNWFilterRuleInst virNWFilterRuleInst;
struct _virNWFilterRuleInst {
diff --git a/src/nwfilter/test_libvirtd_nwfilter.aug.in b/src/nwfilter/test_libvirtd_nwfilter.aug.in
new file mode 100644
index 0000000000..a930f9b428
--- /dev/null
+++ b/src/nwfilter/test_libvirtd_nwfilter.aug.in
@@ -0,0 +1,5 @@
+module Test_libvirtd_nwfilter =
+ @CONFIG@
+
+ test Libvirtd_nwfilter.lns get conf =
+{ "nwfilter_driver" = "nftables" }
--
2.43.0
© 2016 - 2025 Red Hat, Inc.