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
