From nobody Tue Feb 10 01:20:15 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) client-ip=8.43.85.245; envelope-from=devel-bounces@lists.libvirt.org; helo=lists.libvirt.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1770650942; cv=none; d=zohomail.com; s=zohoarc; b=T6DJmzDq2zOw/8ovtE5fk1X1a5ipHlRpTrnELy4dqd6golmbJxu1cbM6EvAIl+vy14ZEnOw8BukBQAVNMG+Ve/fRryHEOrbOmfWWc+t9bVwooQpzJzq6mbFtEpSUDK3W+1ZEaMilP7DmjxXWbV4SIjFw1tuzqST17nrpXuEInnA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1770650942; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Owner:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Subject:Subject:To:To:Message-Id:Reply-To; bh=nyLbKJWy/5AllrJkKgzLTPV6Zjhv7rykG9FTLfD/vcA=; b=GwkYlcJSM0y1+oMVlAgmP0sixGUdNaTMI1hbMHb3AlzeW8Aq26euNS6Kziplzu/0BvvFLQBdW3zn9EadOVhPi1KpCI8zk+FG/gnsXtgvKncr3R99xDMZZcgWj+l2UCD3ebymBlwkPQoWB9Ubt/96x5lRYu4x7CJ1Tslfl36+g7o= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1770650942727247.9935050307024; Mon, 9 Feb 2026 07:29:02 -0800 (PST) Received: by lists.libvirt.org (Postfix, from userid 993) id 00FDC4410F; Mon, 9 Feb 2026 10:29:02 -0500 (EST) Received: from [172.19.199.6] (lists.libvirt.org [8.43.85.245]) by lists.libvirt.org (Postfix) with ESMTP id B8525441C9; Mon, 9 Feb 2026 10:09:34 -0500 (EST) Received: by lists.libvirt.org (Postfix, from userid 993) id D3D0741B21; Mon, 9 Feb 2026 10:01:46 -0500 (EST) Received: from mail-ed1-f47.google.com (mail-ed1-f47.google.com [209.85.208.47]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (3072 bits) server-digest SHA256) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id A1AED4403A for ; Mon, 9 Feb 2026 09:30:14 -0500 (EST) Received: by mail-ed1-f47.google.com with SMTP id 4fb4d7f45d1cf-65940221f7eso7523021a12.0 for ; Mon, 09 Feb 2026 06:30:14 -0800 (PST) Received: from thinkiepadje.home (2a02-a470-a384-0-74c1-2df-7ef3-3ff.fixed6.kpn.net. [2a02:a470:a384:0:74c1:2df:7ef3:3ff]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-b8eda7a4ccbsm396480566b.21.2026.02.09.06.30.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Feb 2026 06:30:12 -0800 (PST) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-26) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-5.3 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED,RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED,SPF_PASS autolearn=unavailable autolearn_force=no version=4.0.1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1770647413; x=1771252213; darn=lists.libvirt.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=nyLbKJWy/5AllrJkKgzLTPV6Zjhv7rykG9FTLfD/vcA=; b=EL8PyfqS5W18e/xud0V1i2utWFibGbVcjEo8jQA+dvRgpMYxvlFJN0LIJLAhdyib8V +WJZJAFq1eux9npDfakrbbZcdlW+OuZhW9VHiEIraItUdpYTBh5QtmvWNGAVjsK3f1C7 bYeZ3+htjj4ebKW1eISplzw5yELJAbqEtPDyD0jvT9f3LwRKUpw4/8SjGfHdfH+KMwJ/ uli2Rdp3qLv+MgXYoWYhpKX0luAdIDt5KS6KUWW6pxlZtAqZTeoVuMPaLBGZSD9m6haM zfRuEeNjdSKFAWLuA2r+6CqBLsv6iehXSlrwmvLu5zKtj71RGORa9DLIBoa22sApTmxi mVGw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770647413; x=1771252213; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=nyLbKJWy/5AllrJkKgzLTPV6Zjhv7rykG9FTLfD/vcA=; b=RPP29xwTmXyXfVSPXUxrZy87acRjrIvCdfVUhSh/1tHd8ODcSRQEluo+MmUw2pRPyP pSift/gopo+rw7zoa41HY+pZ+2/lAvNQ8Z0ms/IASlkfHQbt6I8t4YfWPTV+ofWYgYeF usHWrtC2lGHS4CQpo5lHDNM4cWk1s/iG8P4AZqaBEwzH4hEFi62thahaOvvpJPN3Nw/f kPzt2d0wp052fUYvtPHey1oFWcNVal19rVraoquW8Niy1s8sbmGgjn4YuuvDDEAG720N ktxqKbX5P5i4MsIcG2ahxir0xxXJW/NkZYpeH8F/NcNCRs4e2/gugGej+xrUK0bYolxw uAHQ== X-Gm-Message-State: AOJu0YyTN1B2ht8ZbNDTInc36wUmiiR0phCrQbmZP+tteXRKaV6AVznC 3qCjBqInCbu9JRy8pBkUrOiPaKpfuZ8vhV5vJ3upQuONSSgYpudySWpvdXuL X-Gm-Gg: AZuq6aLMC8zPo43p9lz0+3kRtyHmbpiMmi3k4a3LB3gMIwU05n0RwQF1V9JBzqRgnnP M2hdskddBRAdv8roVa+dqzkhu1tp0BxeAGqUgNDGJR7mdApgmaNvvjLHPHYz2YWzNAQ8a/BUm+Z ytzoN4ZlPHnBLT626B4uKhm4pwqrFYInSpea8H0LsKnQRKdlWZX7gpOSycbL3eNV3/8C4tb6z7J tpNsc4xYVLF9TmBd3iUjYh+k6y1xX4p9weovLrB5rC0/goHRZu6GFVehMZLXAbffk5NJgTmScMP zZ/LqBLcODzgqKCdK81Q4BXdQLBdnV6bzUEwMBohc6SKht/MteidUuKi+Hki8h3RK+nWKBkffA+ W7gIRsPM81LNdNzEyNkx5WdX/VVlVNVZfgueZdgm3mKBSeB49TujU1MSU0MGQGsyoSvMgOEpcdk fxQtW7vk/VXXnOH+VnE8bYBHztGWOlhP8DACKQjBESzx28qCShIor3Z22R6E44kEFjMjnGAIzSQ IwGor0= X-Received: by 2002:a17:907:782:b0:b8e:64e:1fe with SMTP id a640c23a62f3a-b8edf38468dmr713317266b.55.1770647412869; Mon, 09 Feb 2026 06:30:12 -0800 (PST) From: Dion Bosschieter To: devel@lists.libvirt.org Subject: [PATCH v3 4/5] nwfilter: allow use of nftables nwfilter driver via nwfilter.conf Date: Mon, 9 Feb 2026 15:29:52 +0100 Message-ID: <20260209142953.1016258-5-dionbosschieter@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260209142953.1016258-1-dionbosschieter@gmail.com> References: <20260209142953.1016258-1-dionbosschieter@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Message-ID-Hash: E76ACF652MGMTEQUJIDWRERMPRRV43MA X-Message-ID-Hash: E76ACF652MGMTEQUJIDWRERMPRRV43MA X-MailFrom: dionbosschieter@gmail.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; header-match-devel.lists.libvirt.org-0; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: jean-louis@dupond.be, Dion Bosschieter X-Mailman-Version: 3.3.10 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1770650944575154100 Content-Type: text/plain; charset="utf-8" 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 extra nwfilter config options "enable_trace" and "enable_counters" to allow users to toggle nftable driver specific features. Added nftables to *filter_tech_drivers as an available driver option for users to choose from. Signed-off-by: Dion Bosschieter --- libvirt.spec.in | 7 + po/POTFILES | 1 + src/conf/virnwfilterobj.h | 20 -- src/nwfilter/libvirtd_nwfilter.aug | 45 +++++ src/nwfilter/meson.build | 37 ++++ src/nwfilter/nwfilter.conf.in | 50 +++++ src/nwfilter/nwfilter_driver.c | 66 +++---- src/nwfilter/nwfilter_driver_conf.c | 214 +++++++++++++++++++++ src/nwfilter/nwfilter_driver_conf.h | 69 +++++++ src/nwfilter/nwfilter_ebiptables_driver.c | 4 +- src/nwfilter/nwfilter_ebiptables_driver.h | 2 +- src/nwfilter/nwfilter_gentech_driver.c | 65 +++---- src/nwfilter/nwfilter_gentech_driver.h | 5 +- src/nwfilter/nwfilter_nftables_driver.c | 35 ++-- src/nwfilter/nwfilter_tech_driver.c | 1 - src/nwfilter/nwfilter_tech_driver.h | 3 +- src/nwfilter/test_libvirtd_nwfilter.aug.in | 7 + 17 files changed, 511 insertions(+), 120 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/libvirt.spec.in b/libvirt.spec.in index 22c9975d9f..01c0df7cda 100644 --- a/libvirt.spec.in +++ b/libvirt.spec.in @@ -617,8 +617,12 @@ bridge capabilities. Summary: Nwfilter driver plugin for the libvirtd daemon Requires: libvirt-daemon-common =3D %{version}-%{release} Requires: libvirt-libs =3D %{version}-%{release} + %if %{prefer_nftables} +Requires: nftables + %else Requires: iptables Requires: ebtables + %endif =20 %description daemon-driver-nwfilter The nwfilter driver plugin for the libvirtd daemon, providing @@ -2232,6 +2236,9 @@ exit 0 %config(noreplace) %{_sysconfdir}/libvirt/virtnwfilterd.conf %{_datadir}/augeas/lenses/virtnwfilterd.aug %{_datadir}/augeas/lenses/tests/test_virtnwfilterd.aug +%config(noreplace) %{_sysconfdir}/libvirt/nwfilter.conf +%{_datadir}/augeas/lenses/libvirtd_nwfilter.aug +%{_datadir}/augeas/lenses/tests/test_libvirtd_nwfilter.aug %{_unitdir}/virtnwfilterd.service %{_unitdir}/virtnwfilterd.socket %{_unitdir}/virtnwfilterd-ro.socket diff --git a/po/POTFILES b/po/POTFILES index 5d4c27ac00..b77229d9df 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; =20 typedef struct _virNWFilterObjList virNWFilterObjList; =20 -typedef struct _virNWFilterDriverState virNWFilterDriverState; -struct _virNWFilterDriverState { - bool privileged; - - /* pid file FD, ensures two copies of the driver can't use the same ro= ot */ - 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); =20 diff --git a/src/nwfilter/libvirtd_nwfilter.aug b/src/nwfilter/libvirtd_nwf= ilter.aug new file mode 100644 index 0000000000..2a8475b680 --- /dev/null +++ b/src/nwfilter/libvirtd_nwfilter.aug @@ -0,0 +1,45 @@ +(* /etc/libvirt/nwfilter.conf *) + +module Libvirtd_nwfilter =3D + autoload xfm + + let eol =3D del /[ \t]*\n/ "\n" + let value_sep =3D del /[ \t]*=3D[ \t]*/ " =3D " + let indent =3D del /[ \t]*/ "" + + let array_sep =3D del /,[ \t\n]*/ ", " + let array_start =3D del /\[[ \t\n]*/ "[ " + let array_end =3D del /\]/ "]" + + let str_val =3D del /\"/ "\"" . store /[^\"]*/ . del /\"/ "\"" + let bool_val =3D store /0|1/ + let int_val =3D store /[0-9]+/ + let str_array_element =3D [ seq "el" . str_val ] . del /[ \t\n]*/ "" + let str_array_val =3D counter "el" . array_start . ( str_array_element = . ( array_sep . str_array_element ) * ) ? . array_end + + let str_entry (kw:string) =3D [ key kw . value_sep . str_val ] + let bool_entry (kw:string) =3D [ key kw . value_sep . bool_val ] + let int_entry (kw:string) =3D [ key kw . value_sep . int_val ] + let str_array_entry (kw:string) =3D [ key kw . value_sep . str_array_va= l ] + + (* Config entries *) + let firewall_backend_entry =3D str_entry "firewall_backend" + let trace_entry =3D bool_entry "enable_trace" + let counters_entry =3D bool_entry "enable_counters" + + (* Each entry in the config is one of the following ... *) + let entry =3D firewall_backend_entry + | trace_entry + | counters_entry + + let comment =3D [ label "#comment" . del /#[ \t]*/ "# " . store /([^ \= t\n][^\n]*)?/ . del /\n/ "\n" ] + let empty =3D [ label "#empty" . eol ] + + let record =3D indent . entry . eol + + let lns =3D ( record | comment | empty ) * + + let filter =3D incl "/etc/libvirt/nwfilter.conf" + . Util.stdexcl + + let xfm =3D 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 =3D [ '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') ], } =20 + nwfilter_options_conf =3D configuration_data({ + 'FIREWALL_BACKEND_PRIORITY': ', '.join(firewall_backend_priority), + 'FIREWALL_BACKEND': firewall_backend_priority[0], + }) + + nwfilter_conf =3D configure_file( + input: 'nwfilter.conf.in', + output: 'nwfilter.conf', + configuration: nwfilter_options_conf, + ) + + nwfilter_options_hack_conf =3D 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 =3D configure_file( + input: 'test_libvirtd_nwfilter.aug.in', + output: 'test_libvirtd_nwfilter.aug.tmp', + configuration: nwfilter_options_hack_conf, + ) + + virt_conf_files +=3D nwfilter_conf + virt_aug_files +=3D files('libvirtd_nwfilter.aug') + virt_test_aug_files +=3D { + '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 +=3D { 'name': 'virtnwfilterd', } diff --git a/src/nwfilter/nwfilter.conf.in b/src/nwfilter/nwfilter.conf.in new file mode 100644 index 0000000000..f535a34dae --- /dev/null +++ b/src/nwfilter/nwfilter.conf.in @@ -0,0 +1,50 @@ +# Master configuration file for the nwfilter driver. +# All settings described here are optional - if omitted, sensible +# defaults are used. + +# firewall_backend: +# +# 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 firewall_backend 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 libvirtd/virtnwfilterd +# has started *isn't* supported. The change will take place the +# next time that libvirtd/virtnwfilterd is restarted - all existing crea= ted +# firewall rules remain and have to be cleaned up manually.) +# +#firewall_backend =3D "@FIREWALL_BACKEND@" + +# enable_trace: +# +# Enables packet tracing for debugging firewall rules +# +# Supported backends: +# +# nftables - Creates nftables tables root chains with "meta nftrace se= t 1;" setting +# +# Possible values are 0 or 1. Default value is 0. +# +#enable_trace =3D 0 + +# enable_counters: +# +# Enables adding a counter to each rule, helpfull for counting +# how many tracking packets traversed each rule +# +# Supported backends: +# +# nftables - Adds the "counter" argument to nft rules nwfilter creates +# +# Possible values are 0 or 1. Default value is 0. +# +#enable_counters =3D 0 diff --git a/src/nwfilter/nwfilter_driver.c b/src/nwfilter/nwfilter_driver.c index 522cfda022..66f5fa7c18 100644 --- a/src/nwfilter/nwfilter_driver.c +++ b/src/nwfilter/nwfilter_driver.c @@ -26,17 +26,15 @@ =20 #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 =3D NULL; if (!driver) return -1; =20 + cfg =3D virNWFilterDriverGetConfig(driver); + if (driver->privileged) { virNWFilterConfLayerShutdown(); virNWFilterDHCPSnoopShutdown(); @@ -171,11 +172,7 @@ nwfilterStateCleanupLocked(void) nwfilterDriverRemoveDBusMatches(); =20 if (driver->lockFD !=3D -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); } =20 virObjectUnref(driver->bindings); @@ -216,6 +213,7 @@ nwfilterStateInitialize(bool privileged, void *opaque G_GNUC_UNUSED) { VIR_LOCK_GUARD lock =3D virLockGuardLock(&driverMutex); + virNWFilterDriverConfig *cfg; GDBusConnection *sysbus =3D NULL; =20 if (root !=3D NULL) { @@ -236,6 +234,9 @@ nwfilterStateInitialize(bool privileged, driver->updateLockInitialized =3D true; driver->privileged =3D privileged; =20 + if (!(driver->config =3D cfg =3D virNWFilterDriverConfigNew(privileged= ))) + goto error; + if (!(driver->nwfilters =3D virNWFilterObjListNew())) goto error; =20 @@ -245,16 +246,8 @@ nwfilterStateInitialize(bool privileged, if (!privileged) return VIR_DRV_STATE_INIT_SKIPPED; =20 - driver->stateDir =3D 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 =3D - virPidFileAcquire(driver->stateDir, "driver", getpid())) < 0) + virPidFileAcquire(cfg->stateDir, "driver", getpid())) < 0) goto error; =20 if (virNWFilterIPAddrMapInit() < 0) @@ -266,7 +259,7 @@ nwfilterStateInitialize(bool privileged, if (virNWFilterDHCPSnoopInit() < 0) goto error; =20 - if (virNWFilterTechDriversInit(privileged) < 0) + if (virNWFilterTechDriversInit(privileged, cfg) < 0) goto error; =20 if (virNWFilterConfLayerInit(virNWFilterTriggerRebuildImpl, driver) < = 0) @@ -279,26 +272,10 @@ nwfilterStateInitialize(bool privileged, if (sysbus) nwfilterDriverInstallDBusMatches(sysbus); =20 - driver->configDir =3D 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 =3D 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; - } =20 - if (virNWFilterObjListLoadAllConfigs(driver->nwfilters, driver->config= Dir) < 0) - goto error; - - if (virNWFilterBindingObjListLoadAllConfigs(driver->bindings, driver->= bindingDir) < 0) + if (virNWFilterBindingObjListLoadAllConfigs(driver->bindings, cfg->bin= dingDir) < 0) goto error; =20 if (virNWFilterBuildAll(driver, false) < 0) @@ -320,19 +297,22 @@ nwfilterStateInitialize(bool privileged, static int nwfilterStateReload(void) { + g_autoptr(virNWFilterDriverConfig) cfg =3D NULL; if (!driver) return -1; =20 if (!driver->privileged) return 0; =20 + cfg =3D virNWFilterDriverGetConfig(driver); + virNWFilterDHCPSnoopEnd(NULL); /* shut down all threads -- they will be restarted if necessary */ virNWFilterLearnThreadsTerminate(true); =20 VIR_WITH_MUTEX_LOCK_GUARD(&driverMutex) { VIR_WITH_MUTEX_LOCK_GUARD(&driver->updateLock) { - virNWFilterObjListLoadAllConfigs(driver->nwfilters, driver->co= nfigDir); + virNWFilterObjListLoadAllConfigs(driver->nwfilters, cfg->confi= gDir); } =20 =20 @@ -535,6 +515,7 @@ nwfilterDefineXMLFlags(virConnectPtr conn, virNWFilterObj *obj =3D NULL; virNWFilterDef *objdef; virNWFilterPtr nwfilter =3D NULL; + g_autoptr(virNWFilterDriverConfig) cfg =3D virNWFilterDriverGetConfig(= driver); =20 virCheckFlags(VIR_NWFILTER_DEFINE_VALIDATE, NULL); =20 @@ -558,7 +539,7 @@ nwfilterDefineXMLFlags(virConnectPtr conn, def =3D NULL; objdef =3D virNWFilterObjGetDef(obj); =20 - 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 =3D -1; + g_autoptr(virNWFilterDriverConfig) cfg =3D virNWFilterDriverGetConfig(= driver); =20 VIR_WITH_MUTEX_LOCK_GUARD(&driver->updateLock) { if (!(obj =3D nwfilterObjFromNWFilter(nwfilter->uuid))) @@ -604,7 +586,7 @@ nwfilterUndefine(virNWFilterPtr nwfilter) goto cleanup; } =20 - if (virNWFilterDeleteDef(driver->configDir, def) < 0) + if (virNWFilterDeleteDef(cfg->configDir, def) < 0) goto cleanup; =20 virNWFilterObjListRemove(driver->nwfilters, obj); @@ -730,6 +712,7 @@ nwfilterBindingCreateXML(virConnectPtr conn, virNWFilterBindingDef *def; virNWFilterBindingObj *obj =3D NULL; virNWFilterBindingPtr ret =3D NULL; + g_autoptr(virNWFilterDriverConfig) cfg =3D virNWFilterDriverGetConfig(= driver); =20 virCheckFlags(VIR_NWFILTER_BINDING_CREATE_VALIDATE, NULL); =20 @@ -772,7 +755,7 @@ nwfilterBindingCreateXML(virConnectPtr conn, } } =20 - virNWFilterBindingObjSave(obj, driver->bindingDir); + virNWFilterBindingObjSave(obj, cfg->bindingDir); =20 cleanup: if (!obj) @@ -799,6 +782,7 @@ nwfilterBindingDelete(virNWFilterBindingPtr binding) virNWFilterBindingObj *obj; virNWFilterBindingDef *def; int ret =3D -1; + g_autoptr(virNWFilterDriverConfig) cfg =3D virNWFilterDriverGetConfig(= driver); =20 obj =3D virNWFilterBindingObjListFindByPortDev(driver->bindings, bindi= ng->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); =20 ret =3D 0; diff --git a/src/nwfilter/nwfilter_driver_conf.c b/src/nwfilter/nwfilter_dr= iver_conf.c new file mode 100644 index 0000000000..88ed10bfdb --- /dev/null +++ b/src/nwfilter/nwfilter_driver_conf.c @@ -0,0 +1,214 @@ +/* + * 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 + * . + * + */ + +#include +#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 =3D NULL; + g_autofree char *fwBackendStr =3D NULL; + bool fwBackendSelected =3D false; + size_t i; + int fwBackends[] =3D { + FIREWALL_BACKENDS + }; + G_STATIC_ASSERT(G_N_ELEMENTS(fwBackends) > 0 && + G_N_ELEMENTS(fwBackends) <=3D VIR_FIREWALL_BACKEND_LAS= T); + int nFwBackends =3D G_N_ELEMENTS(fwBackends); + + if (access(filename, R_OK) =3D=3D 0) { + + conf =3D virConfReadFile(filename, 0); + if (!conf) + return -1; + + /* use virConfGetValue*(conf, ...) functions to read any settings = into cfg */ + + if (virConfGetValueString(conf, "firewall_backend", &fwBackendStr)= < 0) + return -1; + if (virConfGetValueBool(conf, "enable_trace", &cfg->firewallTracin= g) < 0) + return -1; + if (virConfGetValueBool(conf, "enable_counters", &cfg->ruleCounter= s) < 0) + return -1; + + if (fwBackendStr) { + fwBackends[0] =3D virFirewallBackendTypeFromString(fwBackendSt= r); + nFwBackends =3D 1; + + if (fwBackends[0] < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("unrecognized nwfilter_driver =3D '%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 =3D 0; i < nFwBackends && !fwBackendSelected; i++) { + switch ((virFirewallBackend)fwBackends[i]) { + case VIR_FIREWALL_BACKEND_NONE: + fwBackendSelected =3D true; + break; + + case VIR_FIREWALL_BACKEND_IPTABLES: { + g_autofree char *iptablesInPath =3D virFindFileInPath(IPTABLES= ); + + if (iptablesInPath) + fwBackendSelected =3D true; + break; + } + + case VIR_FIREWALL_BACKEND_NFTABLES: { + g_autofree char *nftablesInPath =3D virFindFileInPath(NFT); + + if (nftablesInPath) + fwBackendSelected =3D 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 =3D 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 failur= e */ + virReportError(VIR_ERR_INTERNAL_ERROR, + _("requested nwfilter_driver '%1$s' is not availabl= e"), + 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 =3D NULL; + g_autofree char *configdir =3D NULL; + g_autofree char *configfile =3D NULL; + + if (virNWFilterConfigInitialize() < 0) + return NULL; + + if (!(cfg =3D virObjectNew(virNWFilterDriverConfigClass))) + return NULL; + + if (!privileged) + return g_steal_pointer(&cfg); + + cfg->stateDir =3D g_strdup(RUNSTATEDIR "/libvirt/nwfilter"); + cfg->configDir =3D g_strdup(SYSCONFDIR "/libvirt/nwfilter"); + cfg->bindingDir =3D g_strdup(RUNSTATEDIR "/libvirt/nwfilter-binding"); + configfile =3D 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 =3D 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_dr= iver_conf.h new file mode 100644 index 0000000000..356b3cb71e --- /dev/null +++ b/src/nwfilter/nwfilter_driver_conf.h @@ -0,0 +1,69 @@ +/* + * 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 + * . + */ + +#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; + + bool firewallTracing; + bool ruleCounters; +}; + +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 ro= ot */ + 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.c b/src/nwfilter/nwfil= ter_ebiptables_driver.c index 6769a2fb42..6b6b3cbd69 100644 --- a/src/nwfilter/nwfilter_ebiptables_driver.c +++ b/src/nwfilter/nwfilter_ebiptables_driver.c @@ -78,7 +78,7 @@ VIR_LOG_INIT("nwfilter.nwfilter_ebiptables_driver"); #define MATCH_PHYSDEV_OUT_OLD_FW "-m", "physdev", "--physdev-out" =20 static int ebtablesRemoveBasicRules(const char *ifname); -static int ebiptablesDriverInit(bool privileged); +static int ebiptablesDriverInit(bool privileged, virNWFilterDriverConfig *= config G_GNUC_UNUSED); static void ebiptablesDriverShutdown(void); static int ebtablesCleanAll(const char *ifname); static int ebiptablesAllTeardown(const char *ifname); @@ -3400,7 +3400,7 @@ virNWFilterTechDriver ebiptables_driver =3D { }; =20 static int -ebiptablesDriverInit(bool privileged) +ebiptablesDriverInit(bool privileged, virNWFilterDriverConfig *config G_GN= UC_UNUSED) { if (!privileged) return 0; diff --git a/src/nwfilter/nwfilter_ebiptables_driver.h b/src/nwfilter/nwfil= ter_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 @@ =20 extern virNWFilterTechDriver ebiptables_driver; =20 -#define EBIPTABLES_DRIVER_ID "ebiptables" +#define EBIPTABLES_DRIVER_ID "iptables" =20 #define IPTABLES_MAX_COMMENT_LENGTH 256 diff --git a/src/nwfilter/nwfilter_gentech_driver.c b/src/nwfilter/nwfilter= _gentech_driver.c index 1465734a54..29f80a8677 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" =20 #define VIR_FROM_THIS VIR_FROM_NWFILTER @@ -48,18 +49,23 @@ static int _virNWFilterTeardownFilter(const char *ifnam= e); =20 static virNWFilterTechDriver *filter_tech_drivers[] =3D { &ebiptables_driver, - NULL + &nftables_driver, }; =20 -int virNWFilterTechDriversInit(bool privileged) +int virNWFilterTechDriversInit(bool privileged, virNWFilterDriverConfig *c= onfig) { size_t i =3D 0; - VIR_DEBUG("Initializing NWFilter technology drivers"); - while (filter_tech_drivers[i]) { - if (!(filter_tech_drivers[i]->flags & TECHDRV_FLAG_INITIALIZED)) - filter_tech_drivers[i]->init(privileged); - i++; + VIR_DEBUG("Initializing NWFilter technology drivers, chosen '%s'", + virFirewallBackendTypeToString(config->firewallBackend)); + + for (i =3D 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(config->firewallBackend))) + filter_tech_drivers[i]->init(privileged, config); } + return 0; } =20 @@ -67,25 +73,20 @@ int virNWFilterTechDriversInit(bool privileged) void virNWFilterTechDriversShutdown(void) { size_t i =3D 0; - while (filter_tech_drivers[i]) { + for (i =3D 0; i < G_N_ELEMENTS(filter_tech_drivers); i++) { if ((filter_tech_drivers[i]->flags & TECHDRV_FLAG_INITIALIZED)) filter_tech_drivers[i]->shutdown(); - i++; } } =20 =20 static virNWFilterTechDriver * -virNWFilterTechDriverForName(const char *name) +virNWFilterInitializedTechDriver(void) { size_t i =3D 0; - while (filter_tech_drivers[i]) { - if (STREQ(filter_tech_drivers[i]->name, name)) { - if ((filter_tech_drivers[i]->flags & TECHDRV_FLAG_INITIALIZED)= =3D=3D 0) - break; + for (i =3D 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(virNWFilterDriverSta= te *driver, bool *foundNewFilter) { int rc =3D -1; - const char *drvname =3D EBIPTABLES_DRIVER_ID; virNWFilterTechDriver *techdriver; virNWFilterObj *obj; virNWFilterDef *filter; @@ -625,12 +625,11 @@ virNWFilterInstantiateFilterUpdate(virNWFilterDriverS= tate *driver, char vmmacaddr[VIR_MAC_STRING_BUFLEN] =3D {0}; virNWFilterVarValue *ipaddr; =20 - techdriver =3D virNWFilterTechDriverForName(drvname); + techdriver =3D virNWFilterInitializedTechDriver(); =20 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; } =20 @@ -768,15 +767,13 @@ virNWFilterUpdateInstantiateFilter(virNWFilterDriverS= tate *driver, static int virNWFilterRollbackUpdateFilter(virNWFilterBindingDef *binding) { - const char *drvname =3D EBIPTABLES_DRIVER_ID; int ifindex; virNWFilterTechDriver *techdriver; =20 - techdriver =3D virNWFilterTechDriverForName(drvname); + techdriver =3D 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; } =20 @@ -793,15 +790,13 @@ virNWFilterRollbackUpdateFilter(virNWFilterBindingDef= *binding) static int virNWFilterTearOldFilter(virNWFilterBindingDef *binding) { - const char *drvname =3D EBIPTABLES_DRIVER_ID; int ifindex; virNWFilterTechDriver *techdriver; =20 - techdriver =3D virNWFilterTechDriverForName(drvname); + techdriver =3D 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; } =20 @@ -818,14 +813,12 @@ virNWFilterTearOldFilter(virNWFilterBindingDef *bindi= ng) static int _virNWFilterTeardownFilter(const char *ifname) { - const char *drvname =3D EBIPTABLES_DRIVER_ID; virNWFilterTechDriver *techdriver; - techdriver =3D virNWFilterTechDriverForName(drvname); + techdriver =3D virNWFilterInitializedTechDriver(); =20 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; } =20 diff --git a/src/nwfilter/nwfilter_gentech_driver.h b/src/nwfilter/nwfilter= _gentech_driver.h index 946d5d3d56..0059ca6bdb 100644 --- a/src/nwfilter/nwfilter_gentech_driver.h +++ b/src/nwfilter/nwfilter_gentech_driver.h @@ -24,8 +24,11 @@ =20 #include "virnwfilterobj.h" #include "virnwfilterbindingdef.h" +#include "nwfilter_driver_conf.h" +#include "virfirewall.h" =20 -int virNWFilterTechDriversInit(bool privileged); + +int virNWFilterTechDriversInit(bool privileged, virNWFilterDriverConfig *c= onfig); void virNWFilterTechDriversShutdown(void); =20 enum instCase { diff --git a/src/nwfilter/nwfilter_nftables_driver.c b/src/nwfilter/nwfilte= r_nftables_driver.c index c7bacb11bb..66394fc321 100644 --- a/src/nwfilter/nwfilter_nftables_driver.c +++ b/src/nwfilter/nwfilter_nftables_driver.c @@ -38,16 +38,20 @@ =20 #define VIR_FROM_THIS VIR_FROM_NWFILTER =20 -/* define nftable root table */ +/* define nftable root tables */ #define NF_ETHERNET_TABLE "libvirt_nwfilter_ethernet" #define NF_INET_TABLE "libvirt_nwfilter_inet" + #define NF_COMMENT \ "{ comment \"Managed by libvirt for network filters: " \ "https://libvirt.org/firewall.html#the-network-filter-driver\"; }" + /* nftables counter can be enabled for firewalls transparency */ -#ifndef NF_COUNTER -# define NF_COUNTER 0 -#endif +static bool counters_enabled; + +/* nftables tracing can be enabled for firewall debugging, +* to find out where packets are flowing towards */ +static bool trace_enabled; =20 /* define chains */ #define IN_CHAIN "postrouting" @@ -67,14 +71,7 @@ =20 #define DEFAULT_POLICY "accept" =20 -#ifndef NF_TRACE -# define NF_TRACE 0 -#endif -#if NF_TRACE -# define TRACE_SETTING "meta nftrace set 1;" -#else -# define TRACE_SETTING "" -#endif +#define TRACE_SETTING "meta nftrace set 1;" =20 #define CHAINSETTINGS "{ }" =20 @@ -84,7 +81,7 @@ =20 #define ROOT_CHAINSETTINGS(chain, defaultPolicy) \ "{ type filter hook "chain" priority %d;" \ - " policy "defaultPolicy"; "TRACE_SETTING" }" + " policy "defaultPolicy"; %s }" =20 VIR_LOG_INIT("nwfilter.nwfilter_nftables_driver"); =20 @@ -126,6 +123,7 @@ static void nftablesCreateTable(virFirewall *fw, const char *tableName) { virFirewallCmd *fwrule =3D NULL; + const char *traceSetting =3D trace_enabled ? TRACE_SETTING : ""; int tablePriority =3D STREQ(tableName, NF_ETHERNET_TABLE) ? 0 : 1; =20 /* define table */ @@ -144,12 +142,12 @@ static void nftablesCreateTable(virFirewall *fw, tableName, IN_CHAIN, NULL); virFirewallCmdAddArgFormat(fw, fwrule, ROOT_CHAINSETTINGS(IN_CHAIN, DEFAULT_POLICY= ), - tablePriority); + tablePriority, traceSetting); fwrule =3D virFirewallAddCmd(fw, layer, "add", "chain", "bridge", tableName, OUT_CHAIN, NULL); virFirewallCmdAddArgFormat(fw, fwrule, ROOT_CHAINSETTINGS(OUT_CHAIN, DEFAULT_POLIC= Y), - tablePriority); + tablePriority, traceSetting); =20 /* add the one jump rule based on the vmap */ fwrule =3D virFirewallAddCmd(fw, layer, "add", "rule", "bridge", table= Name, @@ -1343,7 +1341,7 @@ nftablesCreateRuleInstance(virFirewall *fw, goto cleanup; } =20 - if (NF_COUNTER) + if (counters_enabled) virFirewallCmdAddArg(fw, fwrule, "counter"); =20 /* specify the action for this rule */ @@ -2459,11 +2457,14 @@ nftablesDropAllRules(const char *ifname) } =20 static int -nftablesDriverInit(bool privileged) +nftablesDriverInit(bool privileged, virNWFilterDriverConfig *config G_GNUC= _UNUSED) { if (!privileged) return 0; =20 + trace_enabled =3D config->firewallTracing; + counters_enabled =3D config->ruleCounters; + nftables_driver.flags =3D TECHDRV_FLAG_INITIALIZED; =20 return 0; diff --git a/src/nwfilter/nwfilter_tech_driver.c b/src/nwfilter/nwfilter_te= ch_driver.c index cfe016aef0..f337af05da 100644 --- a/src/nwfilter/nwfilter_tech_driver.c +++ b/src/nwfilter/nwfilter_tech_driver.c @@ -19,7 +19,6 @@ #include =20 #include "nwfilter_tech_driver.h" -#include "nwfilter_conf.h" =20 #define VIR_FROM_THIS VIR_FROM_NWFILTER =20 diff --git a/src/nwfilter/nwfilter_tech_driver.h b/src/nwfilter/nwfilter_te= ch_driver.h index 8f9d605529..e351b7a798 100644 --- a/src/nwfilter/nwfilter_tech_driver.h +++ b/src/nwfilter/nwfilter_tech_driver.h @@ -25,6 +25,7 @@ =20 #include "virnwfilterobj.h" #include "virstring.h" +#include "nwfilter_driver_conf.h" =20 typedef struct _virNWFilterRuleInst virNWFilterRuleInst; struct _virNWFilterRuleInst { @@ -61,7 +62,7 @@ enum virNWFilterProtoIdx { =20 #define virNWFilterUShortMapEntryIdx(IDX, ATT, VAL) [IDX] =3D { .attr =3D = ATT, .val =3D VAL } =20 -typedef int (*virNWFilterTechDrvInit)(bool privileged); +typedef int (*virNWFilterTechDrvInit)(bool privileged, virNWFilterDriverCo= nfig *config); typedef void (*virNWFilterTechDrvShutdown)(void); =20 typedef int (*virNWFilterRuleApplyNewRules)(const char *ifname, diff --git a/src/nwfilter/test_libvirtd_nwfilter.aug.in b/src/nwfilter/test= _libvirtd_nwfilter.aug.in new file mode 100644 index 0000000000..e6e62550e4 --- /dev/null +++ b/src/nwfilter/test_libvirtd_nwfilter.aug.in @@ -0,0 +1,7 @@ +module Test_libvirtd_nwfilter =3D + @CONFIG@ + + test Libvirtd_nwfilter.lns get conf =3D +{ "firewall_backend" =3D "nftables" } +{ "enable_trace" =3D "0" } +{ "enable_counters" =3D "0" } --=20 2.43.0