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 <[email protected]>
---
 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


Reply via email to