[libvirt PATCH 05/28] util: move backend-agnostic virNetfilter*() functions to their own file

Laine Stump posted 28 patches 1 year, 2 months ago
There is a newer version of this series
[libvirt PATCH 05/28] util: move backend-agnostic virNetfilter*() functions to their own file
Posted by Laine Stump 1 year, 2 months ago
These function are all moved into virnetfilter.[ch]. The only
functions from viriptables.[ch] that are still called from the
consumer (network bridge driver) are iptablesSetupPrivateChains()
(which creates the private chains that all iptables rules will be
added to), and iptablesAddOutputFixUdpChecksum() and
iptablesRemoveOutputFixUdpChecksum() (which add/remove rules to fix
improper checksum of DHCP packets, which is something not supported by
nftables)

Signed-off-by: Laine Stump <laine@redhat.com>
---
 src/libvirt_private.syms          |  51 +--
 src/network/bridge_driver_linux.c |   1 +
 src/util/meson.build              |   1 +
 src/util/viriptables.c            | 522 +--------------------------
 src/util/viriptables.h            | 212 +++++------
 src/util/virnetfilter.c           | 570 ++++++++++++++++++++++++++++++
 src/util/virnetfilter.h           | 151 ++++++++
 7 files changed, 849 insertions(+), 659 deletions(-)
 create mode 100644 src/util/virnetfilter.c
 create mode 100644 src/util/virnetfilter.h

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 9f3868bbac..11b84a866a 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2550,30 +2550,6 @@ virInitctlSetRunLevel;
 iptablesAddOutputFixUdpChecksum;
 iptablesRemoveOutputFixUdpChecksum;
 iptablesSetupPrivateChains;
-virNetfilterAddDontMasquerade;
-virNetfilterAddForwardAllowCross;
-virNetfilterAddForwardAllowIn;
-virNetfilterAddForwardAllowOut;
-virNetfilterAddForwardAllowRelatedIn;
-virNetfilterAddForwardMasquerade;
-virNetfilterAddForwardRejectIn;
-virNetfilterAddForwardRejectOut;
-virNetfilterAddTcpInput;
-virNetfilterAddTcpOutput;
-virNetfilterAddUdpInput;
-virNetfilterAddUdpOutput;
-virNetfilterRemoveDontMasquerade;
-virNetfilterRemoveForwardAllowCross;
-virNetfilterRemoveForwardAllowIn;
-virNetfilterRemoveForwardAllowOut;
-virNetfilterRemoveForwardAllowRelatedIn;
-virNetfilterRemoveForwardMasquerade;
-virNetfilterRemoveForwardRejectIn;
-virNetfilterRemoveForwardRejectOut;
-virNetfilterRemoveTcpInput;
-virNetfilterRemoveTcpOutput;
-virNetfilterRemoveUdpInput;
-virNetfilterRemoveUdpOutput;
 
 
 # util/viriscsi.h
@@ -2960,6 +2936,33 @@ virNetDevVPortProfileOpTypeFromString;
 virNetDevVPortProfileOpTypeToString;
 
 
+# util/virnetfilter.h
+virNetfilterAddDontMasquerade;
+virNetfilterAddForwardAllowCross;
+virNetfilterAddForwardAllowIn;
+virNetfilterAddForwardAllowOut;
+virNetfilterAddForwardAllowRelatedIn;
+virNetfilterAddForwardMasquerade;
+virNetfilterAddForwardRejectIn;
+virNetfilterAddForwardRejectOut;
+virNetfilterAddTcpInput;
+virNetfilterAddTcpOutput;
+virNetfilterAddUdpInput;
+virNetfilterAddUdpOutput;
+virNetfilterRemoveDontMasquerade;
+virNetfilterRemoveForwardAllowCross;
+virNetfilterRemoveForwardAllowIn;
+virNetfilterRemoveForwardAllowOut;
+virNetfilterRemoveForwardAllowRelatedIn;
+virNetfilterRemoveForwardMasquerade;
+virNetfilterRemoveForwardRejectIn;
+virNetfilterRemoveForwardRejectOut;
+virNetfilterRemoveTcpInput;
+virNetfilterRemoveTcpOutput;
+virNetfilterRemoveUdpInput;
+virNetfilterRemoveUdpOutput;
+
+
 # util/virnetlink.h
 virNetlinkCommand;
 virNetlinkDelLink;
diff --git a/src/network/bridge_driver_linux.c b/src/network/bridge_driver_linux.c
index da7d78a40a..e03c17b259 100644
--- a/src/network/bridge_driver_linux.c
+++ b/src/network/bridge_driver_linux.c
@@ -22,6 +22,7 @@
 #include <config.h>
 
 #include "virfile.h"
+#include "virnetfilter.h"
 #include "viriptables.h"
 #include "virstring.h"
 #include "virlog.h"
diff --git a/src/util/meson.build b/src/util/meson.build
index c2175f1098..aa570ed02a 100644
--- a/src/util/meson.build
+++ b/src/util/meson.build
@@ -69,6 +69,7 @@ util_sources = [
   'virnetdevveth.c',
   'virnetdevvlan.c',
   'virnetdevvportprofile.c',
+  'virnetfilter.c',
   'virnetlink.c',
   'virnodesuspend.c',
   'virnuma.c',
diff --git a/src/util/viriptables.c b/src/util/viriptables.c
index 8db5bb3e4b..a85f3ea603 100644
--- a/src/util/viriptables.c
+++ b/src/util/viriptables.c
@@ -27,6 +27,7 @@
 #include <sys/stat.h>
 
 #include "internal.h"
+#include "virnetfilter.h"
 #include "viriptables.h"
 #include "virfirewalld.h"
 #include "virerror.h"
@@ -37,11 +38,6 @@ VIR_LOG_INIT("util.iptables");
 
 #define VIR_FROM_THIS VIR_FROM_NONE
 
-enum {
-    VIR_NETFILTER_INSERT = 0,
-    VIR_NETFILTER_DELETE
-};
-
 typedef struct {
     const char *parent;
     const char *child;
@@ -155,7 +151,7 @@ iptablesSetupPrivateChains(virFirewallLayer layer)
 }
 
 
-static void
+void
 iptablesInput(virFirewall *fw,
               virFirewallLayer layer,
               const char *iface,
@@ -176,7 +172,7 @@ iptablesInput(virFirewall *fw,
                        NULL);
 }
 
-static void
+void
 iptablesOutput(virFirewall *fw,
                virFirewallLayer layer,
                const char *iface,
@@ -197,155 +193,11 @@ iptablesOutput(virFirewall *fw,
                        NULL);
 }
 
-/**
- * virNetfilterAddTcpInput:
- * @ctx: pointer to the IP table context
- * @iface: the interface name
- * @port: the TCP port to add
- *
- * Add an input to the IP table allowing access to the given @port on
- * the given @iface interface for TCP packets
- */
-void
-virNetfilterAddTcpInput(virFirewall *fw,
-                        virFirewallLayer layer,
-                        const char *iface,
-                        int port)
-{
-    iptablesInput(fw, layer, iface, port, VIR_NETFILTER_INSERT, 1);
-}
-
-/**
- * virNetfilterRemoveTcpInput:
- * @ctx: pointer to the IP table context
- * @iface: the interface name
- * @port: the TCP port to remove
- *
- * Removes an input from the IP table, hence forbidding access to the given
- * @port on the given @iface interface for TCP packets
- */
-void
-virNetfilterRemoveTcpInput(virFirewall *fw,
-                           virFirewallLayer layer,
-                           const char *iface,
-                           int port)
-{
-    iptablesInput(fw, layer, iface, port, VIR_NETFILTER_DELETE, 1);
-}
-
-/**
- * virNetfilterAddUdpInput:
- * @ctx: pointer to the IP table context
- * @iface: the interface name
- * @port: the UDP port to add
- *
- * Add an input to the IP table allowing access to the given @port on
- * the given @iface interface for UDP packets
- */
-void
-virNetfilterAddUdpInput(virFirewall *fw,
-                        virFirewallLayer layer,
-                        const char *iface,
-                        int port)
-{
-    iptablesInput(fw, layer, iface, port, VIR_NETFILTER_INSERT, 0);
-}
-
-/**
- * virNetfilterRemoveUdpInput:
- * @ctx: pointer to the IP table context
- * @iface: the interface name
- * @port: the UDP port to remove
- *
- * Removes an input from the IP table, hence forbidding access to the given
- * @port on the given @iface interface for UDP packets
- */
-void
-virNetfilterRemoveUdpInput(virFirewall *fw,
-                           virFirewallLayer layer,
-                           const char *iface,
-                           int port)
-{
-    iptablesInput(fw, layer, iface, port, VIR_NETFILTER_DELETE, 0);
-}
-
-/**
- * virNetfilterAddTcpOutput:
- * @ctx: pointer to the IP table context
- * @iface: the interface name
- * @port: the TCP port to add
- *
- * Add an output to the IP table allowing access to the given @port from
- * the given @iface interface for TCP packets
- */
-void
-virNetfilterAddTcpOutput(virFirewall *fw,
-                         virFirewallLayer layer,
-                         const char *iface,
-                         int port)
-{
-    iptablesOutput(fw, layer, iface, port, VIR_NETFILTER_INSERT, 1);
-}
-
-/**
- * virNetfilterRemoveTcpOutput:
- * @ctx: pointer to the IP table context
- * @iface: the interface name
- * @port: the UDP port to remove
- *
- * Removes an output from the IP table, hence forbidding access to the given
- * @port from the given @iface interface for TCP packets
- */
-void
-virNetfilterRemoveTcpOutput(virFirewall *fw,
-                            virFirewallLayer layer,
-                            const char *iface,
-                            int port)
-{
-    iptablesOutput(fw, layer, iface, port, VIR_NETFILTER_DELETE, 1);
-}
-
-/**
- * virNetfilterAddUdpOutput:
- * @ctx: pointer to the IP table context
- * @iface: the interface name
- * @port: the UDP port to add
- *
- * Add an output to the IP table allowing access to the given @port from
- * the given @iface interface for UDP packets
- */
-void
-virNetfilterAddUdpOutput(virFirewall *fw,
-                         virFirewallLayer layer,
-                         const char *iface,
-                         int port)
-{
-    iptablesOutput(fw, layer, iface, port, VIR_NETFILTER_INSERT, 0);
-}
-
-/**
- * virNetfilterRemoveUdpOutput:
- * @ctx: pointer to the IP table context
- * @iface: the interface name
- * @port: the UDP port to remove
- *
- * Removes an output from the IP table, hence forbidding access to the given
- * @port from the given @iface interface for UDP packets
- */
-void
-virNetfilterRemoveUdpOutput(virFirewall *fw,
-                            virFirewallLayer layer,
-                            const char *iface,
-                            int port)
-{
-    iptablesOutput(fw, layer, iface, port, VIR_NETFILTER_DELETE, 0);
-}
-
 
 /* Allow all traffic coming from the bridge, with a valid network address
  * to proceed to WAN
  */
-static int
+int
 iptablesForwardAllowOut(virFirewall *fw,
                         virSocketAddr *netaddr,
                         unsigned int prefix,
@@ -383,59 +235,11 @@ iptablesForwardAllowOut(virFirewall *fw,
     return 0;
 }
 
-/**
- * virNetfilterAddForwardAllowOut:
- * @ctx: pointer to the IP table context
- * @network: the source network name
- * @iface: the source interface name
- * @physdev: the physical output device
- *
- * Add a rule to the IP table context to allow the traffic for the
- * network @network via interface @iface to be forwarded to
- * @physdev device. This allow the outbound traffic on a bridge.
- *
- * Returns 0 in case of success or an error code otherwise
- */
-int
-virNetfilterAddForwardAllowOut(virFirewall *fw,
-                               virSocketAddr *netaddr,
-                               unsigned int prefix,
-                               const char *iface,
-                               const char *physdev)
-{
-    return iptablesForwardAllowOut(fw, netaddr, prefix, iface, physdev,
-                                   VIR_NETFILTER_INSERT);
-}
-
-/**
- * virNetfilterRemoveForwardAllowOut:
- * @ctx: pointer to the IP table context
- * @network: the source network name
- * @iface: the source interface name
- * @physdev: the physical output device
- *
- * Remove a rule from the IP table context hence forbidding forwarding
- * of the traffic for the network @network via interface @iface
- * to the @physdev device output. This stops the outbound traffic on a bridge.
- *
- * Returns 0 in case of success or an error code otherwise
- */
-int
-virNetfilterRemoveForwardAllowOut(virFirewall *fw,
-                                  virSocketAddr *netaddr,
-                                  unsigned int prefix,
-                                  const char *iface,
-                                  const char *physdev)
-{
-    return iptablesForwardAllowOut(fw, netaddr, prefix, iface, physdev,
-                                   VIR_NETFILTER_DELETE);
-}
-
 
 /* Allow all traffic destined to the bridge, with a valid network address
  * and associated with an existing connection
  */
-static int
+int
 iptablesForwardAllowRelatedIn(virFirewall *fw,
                               virSocketAddr *netaddr,
                               unsigned int prefix,
@@ -477,57 +281,10 @@ iptablesForwardAllowRelatedIn(virFirewall *fw,
     return 0;
 }
 
-/**
- * virNetfilterAddForwardAllowRelatedIn:
- * @ctx: pointer to the IP table context
- * @network: the source network name
- * @iface: the output interface name
- * @physdev: the physical input device or NULL
- *
- * Add rules to the IP table context to allow the traffic for the
- * network @network on @physdev device to be forwarded to
- * interface @iface, if it is part of an existing connection.
- *
- * Returns 0 in case of success or an error code otherwise
- */
-int
-virNetfilterAddForwardAllowRelatedIn(virFirewall *fw,
-                                     virSocketAddr *netaddr,
-                                     unsigned int prefix,
-                                     const char *iface,
-                                     const char *physdev)
-{
-    return iptablesForwardAllowRelatedIn(fw, netaddr, prefix, iface, physdev,
-                                         VIR_NETFILTER_INSERT);
-}
-
-/**
- * virNetfilterRemoveForwardAllowRelatedIn:
- * @ctx: pointer to the IP table context
- * @network: the source network name
- * @iface: the output interface name
- * @physdev: the physical input device or NULL
- *
- * Remove rules from the IP table context hence forbidding the traffic for
- * network @network on @physdev device to be forwarded to
- * interface @iface, if it is part of an existing connection.
- *
- * Returns 0 in case of success or an error code otherwise
- */
-int
-virNetfilterRemoveForwardAllowRelatedIn(virFirewall *fw,
-                                        virSocketAddr *netaddr,
-                                        unsigned int prefix,
-                                        const char *iface,
-                                        const char *physdev)
-{
-    return iptablesForwardAllowRelatedIn(fw, netaddr, prefix, iface, physdev,
-                                         VIR_NETFILTER_DELETE);
-}
 
 /* Allow all traffic destined to the bridge, with a valid network address
  */
-static int
+int
 iptablesForwardAllowIn(virFirewall *fw,
                        virSocketAddr *netaddr,
                        unsigned int prefix,
@@ -564,55 +321,8 @@ iptablesForwardAllowIn(virFirewall *fw,
     return 0;
 }
 
-/**
- * virNetfilterAddForwardAllowIn:
- * @ctx: pointer to the IP table context
- * @network: the source network name
- * @iface: the output interface name
- * @physdev: the physical input device or NULL
- *
- * Add rules to the IP table context to allow the traffic for the
- * network @network on @physdev device to be forwarded to
- * interface @iface. This allow the inbound traffic on a bridge.
- *
- * Returns 0 in case of success or an error code otherwise
- */
-int
-virNetfilterAddForwardAllowIn(virFirewall *fw,
-                              virSocketAddr *netaddr,
-                              unsigned int prefix,
-                              const char *iface,
-                              const char *physdev)
-{
-    return iptablesForwardAllowIn(fw, netaddr, prefix, iface, physdev,
-                                  VIR_NETFILTER_INSERT);
-}
 
-/**
- * virNetfilterRemoveForwardAllowIn:
- * @ctx: pointer to the IP table context
- * @network: the source network name
- * @iface: the output interface name
- * @physdev: the physical input device or NULL
- *
- * Remove rules from the IP table context hence forbidding the traffic for
- * network @network on @physdev device to be forwarded to
- * interface @iface. This stops the inbound traffic on a bridge.
- *
- * Returns 0 in case of success or an error code otherwise
- */
-int
-virNetfilterRemoveForwardAllowIn(virFirewall *fw,
-                                 virSocketAddr *netaddr,
-                                 unsigned int prefix,
-                                 const char *iface,
-                                 const char *physdev)
-{
-    return iptablesForwardAllowIn(fw, netaddr, prefix, iface, physdev,
-                                  VIR_NETFILTER_DELETE);
-}
-
-static void
+void
 iptablesForwardAllowCross(virFirewall *fw,
                           virFirewallLayer layer,
                           const char *iface,
@@ -628,45 +338,8 @@ iptablesForwardAllowCross(virFirewall *fw,
                        NULL);
 }
 
-/**
- * virNetfilterAddForwardAllowCross:
- * @ctx: pointer to the IP table context
- * @iface: the input/output interface name
- *
- * Add rules to the IP table context to allow traffic to cross that
- * interface. It allows all traffic between guests on the same bridge
- * represented by that interface.
- *
- * Returns 0 in case of success or an error code otherwise
- */
-void
-virNetfilterAddForwardAllowCross(virFirewall *fw,
-                                 virFirewallLayer layer,
-                                 const char *iface)
-{
-    iptablesForwardAllowCross(fw, layer, iface, VIR_NETFILTER_INSERT);
-}
 
-/**
- * virNetfilterRemoveForwardAllowCross:
- * @ctx: pointer to the IP table context
- * @iface: the input/output interface name
- *
- * Remove rules to the IP table context to block traffic to cross that
- * interface. It forbids traffic between guests on the same bridge
- * represented by that interface.
- *
- * Returns 0 in case of success or an error code otherwise
- */
 void
-virNetfilterRemoveForwardAllowCross(virFirewall *fw,
-                                    virFirewallLayer layer,
-                                    const char *iface)
-{
-    iptablesForwardAllowCross(fw, layer, iface, VIR_NETFILTER_DELETE);
-}
-
-static void
 iptablesForwardRejectOut(virFirewall *fw,
                          virFirewallLayer layer,
                          const char *iface,
@@ -681,44 +354,8 @@ iptablesForwardRejectOut(virFirewall *fw,
                        NULL);
 }
 
-/**
- * virNetfilterAddForwardRejectOut:
- * @ctx: pointer to the IP table context
- * @iface: the output interface name
- *
- * Add rules to the IP table context to forbid all traffic to that
- * interface. It forbids forwarding from the bridge to that interface.
- *
- * Returns 0 in case of success or an error code otherwise
- */
-void
-virNetfilterAddForwardRejectOut(virFirewall *fw,
-                                virFirewallLayer layer,
-                                const char *iface)
-{
-    iptablesForwardRejectOut(fw, layer, iface, VIR_NETFILTER_INSERT);
-}
 
-/**
- * virNetfilterRemoveForwardRejectOut:
- * @ctx: pointer to the IP table context
- * @iface: the output interface name
- *
- * Remove rules from the IP table context forbidding all traffic to that
- * interface. It reallow forwarding from the bridge to that interface.
- *
- * Returns 0 in case of success or an error code otherwise
- */
 void
-virNetfilterRemoveForwardRejectOut(virFirewall *fw,
-                                   virFirewallLayer layer,
-                                   const char *iface)
-{
-    iptablesForwardRejectOut(fw, layer, iface, VIR_NETFILTER_DELETE);
-}
-
-
-static void
 iptablesForwardRejectIn(virFirewall *fw,
                         virFirewallLayer layer,
                         const char *iface,
@@ -733,47 +370,11 @@ iptablesForwardRejectIn(virFirewall *fw,
                        NULL);
 }
 
-/**
- * virNetfilterAddForwardRejectIn:
- * @ctx: pointer to the IP table context
- * @iface: the input interface name
- *
- * Add rules to the IP table context to forbid all traffic from that
- * interface. It forbids forwarding from that interface to the bridge.
- *
- * Returns 0 in case of success or an error code otherwise
- */
-void
-virNetfilterAddForwardRejectIn(virFirewall *fw,
-                               virFirewallLayer layer,
-                               const char *iface)
-{
-    iptablesForwardRejectIn(fw, layer, iface, VIR_NETFILTER_INSERT);
-}
-
-/**
- * virNetfilterRemoveForwardRejectIn:
- * @ctx: pointer to the IP table context
- * @iface: the input interface name
- *
- * Remove rules from the IP table context forbidding all traffic from that
- * interface. It allows forwarding from that interface to the bridge.
- *
- * Returns 0 in case of success or an error code otherwise
- */
-void
-virNetfilterRemoveForwardRejectIn(virFirewall *fw,
-                                  virFirewallLayer layer,
-                                  const char *iface)
-{
-    iptablesForwardRejectIn(fw, layer, iface, VIR_NETFILTER_DELETE);
-}
-
 
 /* Masquerade all traffic coming from the network associated
  * with the bridge
  */
-static int
+int
 iptablesForwardMasquerade(virFirewall *fw,
                           virSocketAddr *netaddr,
                           unsigned int prefix,
@@ -868,65 +469,11 @@ iptablesForwardMasquerade(virFirewall *fw,
     return 0;
 }
 
-/**
- * virNetfilterAddForwardMasquerade:
- * @ctx: pointer to the IP table context
- * @network: the source network name
- * @physdev: the physical input device or NULL
- * @protocol: the network protocol or NULL
- *
- * Add rules to the IP table context to allow masquerading
- * network @network on @physdev. This allow the bridge to
- * masquerade for that network (on @physdev).
- *
- * Returns 0 in case of success or an error code otherwise
- */
-int
-virNetfilterAddForwardMasquerade(virFirewall *fw,
-                                 virSocketAddr *netaddr,
-                                 unsigned int prefix,
-                                 const char *physdev,
-                                 virSocketAddrRange *addr,
-                                 virPortRange *port,
-                                 const char *protocol)
-{
-    return iptablesForwardMasquerade(fw, netaddr, prefix,
-                                     physdev, addr, port, protocol,
-                                     VIR_NETFILTER_INSERT);
-}
-
-/**
- * virNetfilterRemoveForwardMasquerade:
- * @ctx: pointer to the IP table context
- * @network: the source network name
- * @physdev: the physical input device or NULL
- * @protocol: the network protocol or NULL
- *
- * Remove rules from the IP table context to stop masquerading
- * network @network on @physdev. This stops the bridge from
- * masquerading for that network (on @physdev).
- *
- * Returns 0 in case of success or an error code otherwise
- */
-int
-virNetfilterRemoveForwardMasquerade(virFirewall *fw,
-                                    virSocketAddr *netaddr,
-                                    unsigned int prefix,
-                                    const char *physdev,
-                                    virSocketAddrRange *addr,
-                                    virPortRange *port,
-                                    const char *protocol)
-{
-    return iptablesForwardMasquerade(fw, netaddr, prefix,
-                                     physdev, addr, port, protocol,
-                                     VIR_NETFILTER_DELETE);
-}
-
 
 /* Don't masquerade traffic coming from the network associated with the bridge
  * if said traffic targets @destaddr.
  */
-static int
+int
 iptablesForwardDontMasquerade(virFirewall *fw,
                               virSocketAddr *netaddr,
                               unsigned int prefix,
@@ -964,57 +511,6 @@ iptablesForwardDontMasquerade(virFirewall *fw,
     return 0;
 }
 
-/**
- * virNetfilterAddDontMasquerade:
- * @netaddr: the source network name
- * @prefix: prefix (# of 1 bits) of netmask to apply to @netaddr
- * @physdev: the physical output device or NULL
- * @destaddr: the destination network not to masquerade for
- *
- * Add rules to the IP table context to avoid masquerading from
- * @netaddr/@prefix to @destaddr on @physdev. @destaddr must be in a format
- * directly consumable by iptables/nftables, it must not depend on user input or
- * configuration.
- *
- * Returns 0 in case of success or an error code otherwise.
- */
-int
-virNetfilterAddDontMasquerade(virFirewall *fw,
-                              virSocketAddr *netaddr,
-                              unsigned int prefix,
-                              const char *physdev,
-                              const char *destaddr)
-{
-    return iptablesForwardDontMasquerade(fw, netaddr, prefix,
-                                         physdev, destaddr, VIR_NETFILTER_INSERT);
-}
-
-/**
- * virNetfilterRemoveDontMasquerade:
- * @netaddr: the source network name
- * @prefix: prefix (# of 1 bits) of netmask to apply to @netaddr
- * @physdev: the physical output device or NULL
- * @destaddr: the destination network not to masquerade for
- *
- * Remove rules from the IP table context that prevent masquerading from
- * @netaddr/@prefix to @destaddr on @physdev. @destaddr must be in a format
- * directly consumable by iptables/nftables, it must not depend on user input or
- * configuration.
- *
- * Returns 0 in case of success or an error code otherwise.
- */
-int
-virNetfilterRemoveDontMasquerade(virFirewall *fw,
-                                 virSocketAddr *netaddr,
-                                 unsigned int prefix,
-                                 const char *physdev,
-                                 const char *destaddr)
-{
-    return iptablesForwardDontMasquerade(fw, netaddr, prefix,
-                                         physdev, destaddr,
-                                         VIR_NETFILTER_DELETE);
-}
-
 
 static void
 iptablesOutputFixUdpChecksum(virFirewall *fw,
diff --git a/src/util/viriptables.h b/src/util/viriptables.h
index 610c4dccde..6ea589121e 100644
--- a/src/util/viriptables.h
+++ b/src/util/viriptables.h
@@ -23,133 +23,101 @@
 #include "virsocketaddr.h"
 #include "virfirewall.h"
 
+/* These functions are (currently) called directly from the consumer
+ * (e.g. the network driver), and only when the iptables backend is
+ * selected. (Possibly/probably functions should be added to the
+ * netfilter*() API that will call them instead, but that first
+ * requires untangling all the special cases for setting up private
+ * chains that are necessitated by firewalld reloads).
+ */
 int              iptablesSetupPrivateChains      (virFirewallLayer layer);
 
-void             virNetfilterAddTcpInput         (virFirewall *fw,
-                                                  virFirewallLayer layer,
-                                                  const char *iface,
-                                                  int port);
-void             virNetfilterRemoveTcpInput      (virFirewall *fw,
-                                                  virFirewallLayer layer,
-                                                  const char *iface,
-                                                  int port);
-
-void             virNetfilterAddUdpInput         (virFirewall *fw,
-                                                  virFirewallLayer layer,
-                                                  const char *iface,
-                                                  int port);
-void             virNetfilterRemoveUdpInput      (virFirewall *fw,
-                                                  virFirewallLayer layer,
-                                                  const char *iface,
-                                                  int port);
-
-void             virNetfilterAddTcpOutput        (virFirewall *fw,
-                                                  virFirewallLayer layer,
-                                                  const char *iface,
-                                                  int port);
-void             virNetfilterRemoveTcpOutput     (virFirewall *fw,
-                                                  virFirewallLayer layer,
-                                                  const char *iface,
-                                                  int port);
-void             virNetfilterAddUdpOutput        (virFirewall *fw,
-                                                  virFirewallLayer layer,
-                                                  const char *iface,
-                                                  int port);
-void             virNetfilterRemoveUdpOutput     (virFirewall *fw,
-                                                  virFirewallLayer layer,
-                                                  const char *iface,
-                                                  int port);
-
-int              virNetfilterAddForwardAllowOut  (virFirewall *fw,
-                                                  virSocketAddr *netaddr,
-                                                  unsigned int prefix,
-                                                  const char *iface,
-                                                  const char *physdev)
-    G_GNUC_WARN_UNUSED_RESULT;
-int              virNetfilterRemoveForwardAllowOut(virFirewall *fw,
-                                                   virSocketAddr *netaddr,
-                                                   unsigned int prefix,
-                                                   const char *iface,
-                                                   const char *physdev)
-    G_GNUC_WARN_UNUSED_RESULT;
-int              virNetfilterAddForwardAllowRelatedIn(virFirewall *fw,
-                                                      virSocketAddr *netaddr,
-                                                      unsigned int prefix,
-                                                      const char *iface,
-                                                      const char *physdev)
-    G_GNUC_WARN_UNUSED_RESULT;
-int              virNetfilterRemoveForwardAllowRelatedIn(virFirewall *fw,
-                                                         virSocketAddr *netaddr,
-                                                         unsigned int prefix,
-                                                         const char *iface,
-                                                         const char *physdev)
-    G_GNUC_WARN_UNUSED_RESULT;
-
-int              virNetfilterAddForwardAllowIn   (virFirewall *fw,
-                                                  virSocketAddr *netaddr,
-                                                  unsigned int prefix,
-                                                  const char *iface,
-                                                  const char *physdev)
-    G_GNUC_WARN_UNUSED_RESULT;
-int              virNetfilterRemoveForwardAllowIn(virFirewall *fw,
-                                                  virSocketAddr *netaddr,
-                                                  unsigned int prefix,
-                                                  const char *iface,
-                                                  const char *physdev)
-    G_GNUC_WARN_UNUSED_RESULT;
-
-void             virNetfilterAddForwardAllowCross(virFirewall *fw,
-                                                  virFirewallLayer layer,
-                                                  const char *iface);
-void             virNetfilterRemoveForwardAllowCross(virFirewall *fw,
-                                                     virFirewallLayer layer,
-                                                     const char *iface);
-
-void             virNetfilterAddForwardRejectOut (virFirewall *fw,
-                                                  virFirewallLayer layer,
-                                                  const char *iface);
-void             virNetfilterRemoveForwardRejectOut(virFirewall *fw,
-                                                    virFirewallLayer layer,
-                                                    const char *iface);
-
-void             virNetfilterAddForwardRejectIn  (virFirewall *fw,
-                                                  virFirewallLayer layer,
-                                                  const char *iface);
-void             virNetfilterRemoveForwardRejectIn(virFirewall *fw,
-                                                   virFirewallLayer layery,
-                                                   const char *iface);
-
-int              virNetfilterAddForwardMasquerade(virFirewall *fw,
-                                                  virSocketAddr *netaddr,
-                                                  unsigned int prefix,
-                                                  const char *physdev,
-                                                  virSocketAddrRange *addr,
-                                                  virPortRange *port,
-                                                  const char *protocol)
-    G_GNUC_WARN_UNUSED_RESULT;
-int              virNetfilterRemoveForwardMasquerade(virFirewall *fw,
-                                                     virSocketAddr *netaddr,
-                                                     unsigned int prefix,
-                                                     const char *physdev,
-                                                     virSocketAddrRange *addr,
-                                                     virPortRange *port,
-                                                     const char *protocol)
-    G_GNUC_WARN_UNUSED_RESULT;
-int              virNetfilterAddDontMasquerade   (virFirewall *fw,
-                                                  virSocketAddr *netaddr,
-                                                  unsigned int prefix,
-                                                  const char *physdev,
-                                                  const char *destaddr)
-    G_GNUC_WARN_UNUSED_RESULT;
-int              virNetfilterRemoveDontMasquerade(virFirewall *fw,
-                                                  virSocketAddr *netaddr,
-                                                  unsigned int prefix,
-                                                  const char *physdev,
-                                                  const char *destaddr)
-    G_GNUC_WARN_UNUSED_RESULT;
 void             iptablesAddOutputFixUdpChecksum (virFirewall *fw,
                                                   const char *iface,
                                                   int port);
 void             iptablesRemoveOutputFixUdpChecksum (virFirewall *fw,
                                                      const char *iface,
                                                      int port);
+
+/* These functions are only called from virnetfilter.c. Each can be
+ * called with an action of VIR_NETFILTER_INSERT or
+ * VIR_NETFILTER_DELETE, to add or remove the described rule(s) in the
+ * appropriate chain.
+ */
+
+void
+iptablesInput(virFirewall *fw,
+              virFirewallLayer layer,
+              const char *iface,
+              int port,
+              int action,
+              int tcp);
+
+void
+iptablesOutput(virFirewall *fw,
+               virFirewallLayer layer,
+               const char *iface,
+               int port,
+               int action,
+               int tcp);
+
+int
+iptablesForwardAllowOut(virFirewall *fw,
+                        virSocketAddr *netaddr,
+                        unsigned int prefix,
+                        const char *iface,
+                        const char *physdev,
+                        int action);
+
+int
+iptablesForwardAllowRelatedIn(virFirewall *fw,
+                              virSocketAddr *netaddr,
+                              unsigned int prefix,
+                              const char *iface,
+                              const char *physdev,
+                              int action);
+
+int
+iptablesForwardAllowIn(virFirewall *fw,
+                       virSocketAddr *netaddr,
+                       unsigned int prefix,
+                       const char *iface,
+                       const char *physdev,
+                       int action);
+
+
+void
+iptablesForwardAllowCross(virFirewall *fw,
+                          virFirewallLayer layer,
+                          const char *iface,
+                          int action);
+
+void
+iptablesForwardRejectOut(virFirewall *fw,
+                         virFirewallLayer layer,
+                         const char *iface,
+                         int action);
+
+void
+iptablesForwardRejectIn(virFirewall *fw,
+                        virFirewallLayer layer,
+                        const char *iface,
+                        int action);
+
+int
+iptablesForwardMasquerade(virFirewall *fw,
+                          virSocketAddr *netaddr,
+                          unsigned int prefix,
+                          const char *physdev,
+                          virSocketAddrRange *addr,
+                          virPortRange *port,
+                          const char *protocol,
+                          int action);
+
+int
+iptablesForwardDontMasquerade(virFirewall *fw,
+                              virSocketAddr *netaddr,
+                              unsigned int prefix,
+                              const char *physdev,
+                              const char *destaddr,
+                              int action);
diff --git a/src/util/virnetfilter.c b/src/util/virnetfilter.c
new file mode 100644
index 0000000000..efe2ca01dc
--- /dev/null
+++ b/src/util/virnetfilter.c
@@ -0,0 +1,570 @@
+/*
+ * virnetfilter.c: backend-agnostic packet filter helper APIs
+ *
+ * Copyright (C) 2023 Red Hat, Inc.
+ *
+ * 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 <stdarg.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "internal.h"
+#include "virnetfilter.h"
+#include "viriptables.h"
+#include "vircommand.h"
+#include "viralloc.h"
+#include "virerror.h"
+#include "virfile.h"
+#include "virlog.h"
+#include "virthread.h"
+#include "virstring.h"
+#include "virutil.h"
+#include "virhash.h"
+
+VIR_LOG_INIT("util.netfilter");
+
+#define VIR_FROM_THIS VIR_FROM_NONE
+
+
+/**
+ * virNetfilterAddTcpInput:
+ * @ctx: pointer to the IP table context
+ * @iface: the interface name
+ * @port: the TCP port to add
+ *
+ * Add an input to the IP table allowing access to the given @port on
+ * the given @iface interface for TCP packets
+ */
+void
+virNetfilterAddTcpInput(virFirewall *fw,
+                        virFirewallLayer layer,
+                        const char *iface,
+                        int port)
+{
+    iptablesInput(fw, layer, iface, port, VIR_NETFILTER_INSERT, 1);
+}
+
+
+/**
+ * virNetfilterRemoveTcpInput:
+ * @ctx: pointer to the IP table context
+ * @iface: the interface name
+ * @port: the TCP port to remove
+ *
+ * Removes an input from the IP table, hence forbidding access to the given
+ * @port on the given @iface interface for TCP packets
+ */
+void
+virNetfilterRemoveTcpInput(virFirewall *fw,
+                           virFirewallLayer layer,
+                           const char *iface,
+                           int port)
+{
+    iptablesInput(fw, layer, iface, port, VIR_NETFILTER_DELETE, 1);
+}
+
+
+/**
+ * virNetfilterAddUdpInput:
+ * @ctx: pointer to the IP table context
+ * @iface: the interface name
+ * @port: the UDP port to add
+ *
+ * Add an input to the IP table allowing access to the given @port on
+ * the given @iface interface for UDP packets
+ */
+void
+virNetfilterAddUdpInput(virFirewall *fw,
+                        virFirewallLayer layer,
+                        const char *iface,
+                        int port)
+{
+    iptablesInput(fw, layer, iface, port, VIR_NETFILTER_INSERT, 0);
+}
+
+
+/**
+ * virNetfilterRemoveUdpInput:
+ * @ctx: pointer to the IP table context
+ * @iface: the interface name
+ * @port: the UDP port to remove
+ *
+ * Removes an input from the IP table, hence forbidding access to the given
+ * @port on the given @iface interface for UDP packets
+ */
+void
+virNetfilterRemoveUdpInput(virFirewall *fw,
+                           virFirewallLayer layer,
+                           const char *iface,
+                           int port)
+{
+    iptablesInput(fw, layer, iface, port, VIR_NETFILTER_DELETE, 0);
+}
+
+
+/**
+ * virNetfilterAddTcpOutput:
+ * @ctx: pointer to the IP table context
+ * @iface: the interface name
+ * @port: the TCP port to add
+ *
+ * Add an output to the IP table allowing access to the given @port from
+ * the given @iface interface for TCP packets
+ */
+void
+virNetfilterAddTcpOutput(virFirewall *fw,
+                         virFirewallLayer layer,
+                         const char *iface,
+                         int port)
+{
+    iptablesOutput(fw, layer, iface, port, VIR_NETFILTER_INSERT, 1);
+}
+
+
+/**
+ * virNetfilterRemoveTcpOutput:
+ * @ctx: pointer to the IP table context
+ * @iface: the interface name
+ * @port: the UDP port to remove
+ *
+ * Removes an output from the IP table, hence forbidding access to the given
+ * @port from the given @iface interface for TCP packets
+ */
+void
+virNetfilterRemoveTcpOutput(virFirewall *fw,
+                            virFirewallLayer layer,
+                            const char *iface,
+                            int port)
+{
+    iptablesOutput(fw, layer, iface, port, VIR_NETFILTER_DELETE, 1);
+}
+
+
+/**
+ * virNetfilterAddUdpOutput:
+ * @ctx: pointer to the IP table context
+ * @iface: the interface name
+ * @port: the UDP port to add
+ *
+ * Add an output to the IP table allowing access to the given @port from
+ * the given @iface interface for UDP packets
+ */
+void
+virNetfilterAddUdpOutput(virFirewall *fw,
+                         virFirewallLayer layer,
+                         const char *iface,
+                         int port)
+{
+    iptablesOutput(fw, layer, iface, port, VIR_NETFILTER_INSERT, 0);
+}
+
+
+/**
+ * virNetfilterRemoveUdpOutput:
+ * @ctx: pointer to the IP table context
+ * @iface: the interface name
+ * @port: the UDP port to remove
+ *
+ * Removes an output from the IP table, hence forbidding access to the given
+ * @port from the given @iface interface for UDP packets
+ */
+void
+virNetfilterRemoveUdpOutput(virFirewall *fw,
+                            virFirewallLayer layer,
+                            const char *iface,
+                            int port)
+{
+    iptablesOutput(fw, layer, iface, port, VIR_NETFILTER_DELETE, 0);
+}
+
+
+/**
+ * virNetfilterAddForwardAllowOut:
+ * @ctx: pointer to the IP table context
+ * @network: the source network name
+ * @iface: the source interface name
+ * @physdev: the physical output device
+ *
+ * Add a rule to the IP table context to allow the traffic for the
+ * network @network via interface @iface to be forwarded to
+ * @physdev device. This allow the outbound traffic on a bridge.
+ *
+ * Returns 0 in case of success or an error code otherwise
+ */
+int
+virNetfilterAddForwardAllowOut(virFirewall *fw,
+                               virSocketAddr *netaddr,
+                               unsigned int prefix,
+                               const char *iface,
+                               const char *physdev)
+{
+    return iptablesForwardAllowOut(fw, netaddr, prefix, iface, physdev,
+                                   VIR_NETFILTER_INSERT);
+}
+
+
+/**
+ * virNetfilterRemoveForwardAllowOut:
+ * @ctx: pointer to the IP table context
+ * @network: the source network name
+ * @iface: the source interface name
+ * @physdev: the physical output device
+ *
+ * Remove a rule from the IP table context hence forbidding forwarding
+ * of the traffic for the network @network via interface @iface
+ * to the @physdev device output. This stops the outbound traffic on a bridge.
+ *
+ * Returns 0 in case of success or an error code otherwise
+ */
+int
+virNetfilterRemoveForwardAllowOut(virFirewall *fw,
+                                  virSocketAddr *netaddr,
+                                  unsigned int prefix,
+                                  const char *iface,
+                                  const char *physdev)
+{
+    return iptablesForwardAllowOut(fw, netaddr, prefix, iface, physdev,
+                                   VIR_NETFILTER_DELETE);
+}
+
+
+/**
+ * virNetfilterAddForwardAllowRelatedIn:
+ * @ctx: pointer to the IP table context
+ * @network: the source network name
+ * @iface: the output interface name
+ * @physdev: the physical input device or NULL
+ *
+ * Add rules to the IP table context to allow the traffic for the
+ * network @network on @physdev device to be forwarded to
+ * interface @iface, if it is part of an existing connection.
+ *
+ * Returns 0 in case of success or an error code otherwise
+ */
+int
+virNetfilterAddForwardAllowRelatedIn(virFirewall *fw,
+                                     virSocketAddr *netaddr,
+                                     unsigned int prefix,
+                                     const char *iface,
+                                     const char *physdev)
+{
+    return iptablesForwardAllowRelatedIn(fw, netaddr, prefix, iface, physdev,
+                                         VIR_NETFILTER_INSERT);
+}
+
+
+/**
+ * virNetfilterRemoveForwardAllowRelatedIn:
+ * @ctx: pointer to the IP table context
+ * @network: the source network name
+ * @iface: the output interface name
+ * @physdev: the physical input device or NULL
+ *
+ * Remove rules from the IP table context hence forbidding the traffic for
+ * network @network on @physdev device to be forwarded to
+ * interface @iface, if it is part of an existing connection.
+ *
+ * Returns 0 in case of success or an error code otherwise
+ */
+int
+virNetfilterRemoveForwardAllowRelatedIn(virFirewall *fw,
+                                        virSocketAddr *netaddr,
+                                        unsigned int prefix,
+                                        const char *iface,
+                                        const char *physdev)
+{
+    return iptablesForwardAllowRelatedIn(fw, netaddr, prefix, iface, physdev,
+                                         VIR_NETFILTER_DELETE);
+}
+
+
+/**
+ * virNetfilterAddForwardAllowIn:
+ * @ctx: pointer to the IP table context
+ * @network: the source network name
+ * @iface: the output interface name
+ * @physdev: the physical input device or NULL
+ *
+ * Add rules to the IP table context to allow the traffic for the
+ * network @network on @physdev device to be forwarded to
+ * interface @iface. This allow the inbound traffic on a bridge.
+ *
+ * Returns 0 in case of success or an error code otherwise
+ */
+int
+virNetfilterAddForwardAllowIn(virFirewall *fw,
+                              virSocketAddr *netaddr,
+                              unsigned int prefix,
+                              const char *iface,
+                              const char *physdev)
+{
+    return iptablesForwardAllowIn(fw, netaddr, prefix, iface, physdev,
+                                  VIR_NETFILTER_INSERT);
+}
+
+
+/**
+ * virNetfilterRemoveForwardAllowIn:
+ * @ctx: pointer to the IP table context
+ * @network: the source network name
+ * @iface: the output interface name
+ * @physdev: the physical input device or NULL
+ *
+ * Remove rules from the IP table context hence forbidding the traffic for
+ * network @network on @physdev device to be forwarded to
+ * interface @iface. This stops the inbound traffic on a bridge.
+ *
+ * Returns 0 in case of success or an error code otherwise
+ */
+int
+virNetfilterRemoveForwardAllowIn(virFirewall *fw,
+                                 virSocketAddr *netaddr,
+                                 unsigned int prefix,
+                                 const char *iface,
+                                 const char *physdev)
+{
+    return iptablesForwardAllowIn(fw, netaddr, prefix, iface, physdev,
+                                  VIR_NETFILTER_DELETE);
+}
+
+
+/**
+ * virNetfilterAddForwardAllowCross:
+ * @ctx: pointer to the IP table context
+ * @iface: the input/output interface name
+ *
+ * Add rules to the IP table context to allow traffic to cross that
+ * interface. It allows all traffic between guests on the same bridge
+ * represented by that interface.
+ *
+ * Returns 0 in case of success or an error code otherwise
+ */
+void
+virNetfilterAddForwardAllowCross(virFirewall *fw,
+                                 virFirewallLayer layer,
+                                 const char *iface)
+{
+    iptablesForwardAllowCross(fw, layer, iface, VIR_NETFILTER_INSERT);
+}
+
+
+/**
+ * virNetfilterRemoveForwardAllowCross:
+ * @ctx: pointer to the IP table context
+ * @iface: the input/output interface name
+ *
+ * Remove rules to the IP table context to block traffic to cross that
+ * interface. It forbids traffic between guests on the same bridge
+ * represented by that interface.
+ *
+ * Returns 0 in case of success or an error code otherwise
+ */
+void
+virNetfilterRemoveForwardAllowCross(virFirewall *fw,
+                                    virFirewallLayer layer,
+                                    const char *iface)
+{
+    iptablesForwardAllowCross(fw, layer, iface, VIR_NETFILTER_DELETE);
+}
+
+
+/**
+ * virNetfilterAddForwardRejectOut:
+ * @ctx: pointer to the IP table context
+ * @iface: the output interface name
+ *
+ * Add rules to the IP table context to forbid all traffic to that
+ * interface. It forbids forwarding from the bridge to that interface.
+ *
+ * Returns 0 in case of success or an error code otherwise
+ */
+void
+virNetfilterAddForwardRejectOut(virFirewall *fw,
+                                virFirewallLayer layer,
+                                const char *iface)
+{
+    iptablesForwardRejectOut(fw, layer, iface, VIR_NETFILTER_INSERT);
+}
+
+/**
+ * virNetfilterRemoveForwardRejectOut:
+ * @ctx: pointer to the IP table context
+ * @iface: the output interface name
+ *
+ * Remove rules from the IP table context forbidding all traffic to that
+ * interface. It reallow forwarding from the bridge to that interface.
+ *
+ * Returns 0 in case of success or an error code otherwise
+ */
+void
+virNetfilterRemoveForwardRejectOut(virFirewall *fw,
+                                   virFirewallLayer layer,
+                                   const char *iface)
+{
+    iptablesForwardRejectOut(fw, layer, iface, VIR_NETFILTER_DELETE);
+}
+
+
+/**
+ * virNetfilterAddForwardRejectIn:
+ * @ctx: pointer to the IP table context
+ * @iface: the input interface name
+ *
+ * Add rules to the IP table context to forbid all traffic from that
+ * interface. It forbids forwarding from that interface to the bridge.
+ *
+ * Returns 0 in case of success or an error code otherwise
+ */
+void
+virNetfilterAddForwardRejectIn(virFirewall *fw,
+                               virFirewallLayer layer,
+                               const char *iface)
+{
+    iptablesForwardRejectIn(fw, layer, iface, VIR_NETFILTER_INSERT);
+}
+
+
+/**
+ * virNetfilterRemoveForwardRejectIn:
+ * @ctx: pointer to the IP table context
+ * @iface: the input interface name
+ *
+ * Remove rules from the IP table context forbidding all traffic from that
+ * interface. It allows forwarding from that interface to the bridge.
+ *
+ * Returns 0 in case of success or an error code otherwise
+ */
+void
+virNetfilterRemoveForwardRejectIn(virFirewall *fw,
+                                  virFirewallLayer layer,
+                                  const char *iface)
+{
+    iptablesForwardRejectIn(fw, layer, iface, VIR_NETFILTER_DELETE);
+}
+
+
+/**
+ * virNetfilterAddForwardMasquerade:
+ * @ctx: pointer to the IP table context
+ * @network: the source network name
+ * @physdev: the physical input device or NULL
+ * @protocol: the network protocol or NULL
+ *
+ * Add rules to the IP table context to allow masquerading
+ * network @network on @physdev. This allow the bridge to
+ * masquerade for that network (on @physdev).
+ *
+ * Returns 0 in case of success or an error code otherwise
+ */
+int
+virNetfilterAddForwardMasquerade(virFirewall *fw,
+                                 virSocketAddr *netaddr,
+                                 unsigned int prefix,
+                                 const char *physdev,
+                                 virSocketAddrRange *addr,
+                                 virPortRange *port,
+                                 const char *protocol)
+{
+    return iptablesForwardMasquerade(fw, netaddr, prefix,
+                                     physdev, addr, port, protocol,
+                                     VIR_NETFILTER_INSERT);
+}
+
+
+/**
+ * virNetfilterRemoveForwardMasquerade:
+ * @ctx: pointer to the IP table context
+ * @network: the source network name
+ * @physdev: the physical input device or NULL
+ * @protocol: the network protocol or NULL
+ *
+ * Remove rules from the IP table context to stop masquerading
+ * network @network on @physdev. This stops the bridge from
+ * masquerading for that network (on @physdev).
+ *
+ * Returns 0 in case of success or an error code otherwise
+ */
+int
+virNetfilterRemoveForwardMasquerade(virFirewall *fw,
+                                    virSocketAddr *netaddr,
+                                    unsigned int prefix,
+                                    const char *physdev,
+                                    virSocketAddrRange *addr,
+                                    virPortRange *port,
+                                    const char *protocol)
+{
+    return iptablesForwardMasquerade(fw, netaddr, prefix,
+                                     physdev, addr, port, protocol,
+                                     VIR_NETFILTER_DELETE);
+}
+
+
+/**
+ * virNetfilterAddDontMasquerade:
+ * @netaddr: the source network name
+ * @prefix: prefix (# of 1 bits) of netmask to apply to @netaddr
+ * @physdev: the physical output device or NULL
+ * @destaddr: the destination network not to masquerade for
+ *
+ * Add rules to the IP table context to avoid masquerading from
+ * @netaddr/@prefix to @destaddr on @physdev. @destaddr must be in a format
+ * directly consumable by iptables/nftables, it must not depend on user input or
+ * configuration.
+ *
+ * Returns 0 in case of success or an error code otherwise.
+ */
+int
+virNetfilterAddDontMasquerade(virFirewall *fw,
+                              virSocketAddr *netaddr,
+                              unsigned int prefix,
+                              const char *physdev,
+                              const char *destaddr)
+{
+    return iptablesForwardDontMasquerade(fw, netaddr, prefix,
+                                         physdev, destaddr, VIR_NETFILTER_INSERT);
+}
+
+
+/**
+ * virNetfilterRemoveDontMasquerade:
+ * @netaddr: the source network name
+ * @prefix: prefix (# of 1 bits) of netmask to apply to @netaddr
+ * @physdev: the physical output device or NULL
+ * @destaddr: the destination network not to masquerade for
+ *
+ * Remove rules from the IP table context that prevent masquerading from
+ * @netaddr/@prefix to @destaddr on @physdev. @destaddr must be in a format
+ * directly consumable by iptables/nftables, it must not depend on user input or
+ * configuration.
+ *
+ * Returns 0 in case of success or an error code otherwise.
+ */
+int
+virNetfilterRemoveDontMasquerade(virFirewall *fw,
+                                 virSocketAddr *netaddr,
+                                 unsigned int prefix,
+                                 const char *physdev,
+                                 const char *destaddr)
+{
+    return iptablesForwardDontMasquerade(fw, netaddr, prefix,
+                                         physdev, destaddr,
+                                         VIR_NETFILTER_DELETE);
+}
diff --git a/src/util/virnetfilter.h b/src/util/virnetfilter.h
new file mode 100644
index 0000000000..c75f7eccbd
--- /dev/null
+++ b/src/util/virnetfilter.h
@@ -0,0 +1,151 @@
+/*
+ * virnetfilter.h: backend-agnostic packet filter helper APIs
+ *
+ * Copyright (C) 2023 Red Hat, Inc.
+ *
+ * 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 "virsocketaddr.h"
+#include "virfirewall.h"
+
+enum {
+    VIR_NETFILTER_INSERT = 0,
+    VIR_NETFILTER_DELETE
+};
+
+void             virNetfilterAddTcpInput         (virFirewall *fw,
+                                                  virFirewallLayer layer,
+                                                  const char *iface,
+                                                  int port);
+void             virNetfilterRemoveTcpInput      (virFirewall *fw,
+                                                  virFirewallLayer layer,
+                                                  const char *iface,
+                                                  int port);
+void             virNetfilterAddUdpInput         (virFirewall *fw,
+                                                  virFirewallLayer layer,
+                                                  const char *iface,
+                                                  int port);
+void             virNetfilterRemoveUdpInput      (virFirewall *fw,
+                                                  virFirewallLayer layer,
+                                                  const char *iface,
+                                                  int port);
+
+void             virNetfilterAddTcpOutput        (virFirewall *fw,
+                                                  virFirewallLayer layer,
+                                                  const char *iface,
+                                                  int port);
+void             virNetfilterRemoveTcpOutput     (virFirewall *fw,
+                                                  virFirewallLayer layer,
+                                                  const char *iface,
+                                                  int port);
+void             virNetfilterAddUdpOutput        (virFirewall *fw,
+                                                  virFirewallLayer layer,
+                                                  const char *iface,
+                                                  int port);
+void             virNetfilterRemoveUdpOutput     (virFirewall *fw,
+                                                  virFirewallLayer layer,
+                                                  const char *iface,
+                                                  int port);
+
+int              virNetfilterAddForwardAllowOut  (virFirewall *fw,
+                                                  virSocketAddr *netaddr,
+                                                  unsigned int prefix,
+                                                  const char *iface,
+                                                  const char *physdev)
+    G_GNUC_WARN_UNUSED_RESULT;
+int              virNetfilterRemoveForwardAllowOut(virFirewall *fw,
+                                                   virSocketAddr *netaddr,
+                                                   unsigned int prefix,
+                                                   const char *iface,
+                                                   const char *physdev)
+    G_GNUC_WARN_UNUSED_RESULT;
+int              virNetfilterAddForwardAllowRelatedIn(virFirewall *fw,
+                                                      virSocketAddr *netaddr,
+                                                      unsigned int prefix,
+                                                      const char *iface,
+                                                      const char *physdev)
+    G_GNUC_WARN_UNUSED_RESULT;
+int              virNetfilterRemoveForwardAllowRelatedIn(virFirewall *fw,
+                                                         virSocketAddr *netaddr,
+                                                         unsigned int prefix,
+                                                         const char *iface,
+                                                         const char *physdev)
+    G_GNUC_WARN_UNUSED_RESULT;
+
+int              virNetfilterAddForwardAllowIn   (virFirewall *fw,
+                                                  virSocketAddr *netaddr,
+                                                  unsigned int prefix,
+                                                  const char *iface,
+                                                  const char *physdev)
+    G_GNUC_WARN_UNUSED_RESULT;
+int              virNetfilterRemoveForwardAllowIn(virFirewall *fw,
+                                                  virSocketAddr *netaddr,
+                                                  unsigned int prefix,
+                                                  const char *iface,
+                                                  const char *physdev)
+    G_GNUC_WARN_UNUSED_RESULT;
+
+void             virNetfilterAddForwardAllowCross(virFirewall *fw,
+                                                  virFirewallLayer layer,
+                                                  const char *iface);
+void             virNetfilterRemoveForwardAllowCross(virFirewall *fw,
+                                                     virFirewallLayer layer,
+                                                     const char *iface);
+
+void             virNetfilterAddForwardRejectOut (virFirewall *fw,
+                                                  virFirewallLayer layer,
+                                                  const char *iface);
+void             virNetfilterRemoveForwardRejectOut(virFirewall *fw,
+                                                    virFirewallLayer layer,
+                                                    const char *iface);
+
+void             virNetfilterAddForwardRejectIn  (virFirewall *fw,
+                                                  virFirewallLayer layer,
+                                                  const char *iface);
+void             virNetfilterRemoveForwardRejectIn(virFirewall *fw,
+                                                   virFirewallLayer layery,
+                                                   const char *iface);
+
+int              virNetfilterAddForwardMasquerade(virFirewall *fw,
+                                                  virSocketAddr *netaddr,
+                                                  unsigned int prefix,
+                                                  const char *physdev,
+                                                  virSocketAddrRange *addr,
+                                                  virPortRange *port,
+                                                  const char *protocol)
+    G_GNUC_WARN_UNUSED_RESULT;
+int              virNetfilterRemoveForwardMasquerade(virFirewall *fw,
+                                                     virSocketAddr *netaddr,
+                                                     unsigned int prefix,
+                                                     const char *physdev,
+                                                     virSocketAddrRange *addr,
+                                                     virPortRange *port,
+                                                     const char *protocol)
+    G_GNUC_WARN_UNUSED_RESULT;
+int              virNetfilterAddDontMasquerade   (virFirewall *fw,
+                                                  virSocketAddr *netaddr,
+                                                  unsigned int prefix,
+                                                  const char *physdev,
+                                                  const char *destaddr)
+    G_GNUC_WARN_UNUSED_RESULT;
+int              virNetfilterRemoveDontMasquerade(virFirewall *fw,
+                                                  virSocketAddr *netaddr,
+                                                  unsigned int prefix,
+                                                  const char *physdev,
+                                                  const char *destaddr)
+    G_GNUC_WARN_UNUSED_RESULT;
-- 
2.39.2
Re: [libvirt PATCH 05/28] util: move backend-agnostic virNetfilter*() functions to their own file
Posted by Daniel P. Berrangé 1 year, 2 months ago
On Sun, Apr 30, 2023 at 11:19:20PM -0400, Laine Stump wrote:
> These function are all moved into virnetfilter.[ch]. The only
> functions from viriptables.[ch] that are still called from the
> consumer (network bridge driver) are iptablesSetupPrivateChains()
> (which creates the private chains that all iptables rules will be
> added to), and iptablesAddOutputFixUdpChecksum() and
> iptablesRemoveOutputFixUdpChecksum() (which add/remove rules to fix
> improper checksum of DHCP packets, which is something not supported by
> nftables)
> 
> Signed-off-by: Laine Stump <laine@redhat.com>
> ---
>  src/libvirt_private.syms          |  51 +--
>  src/network/bridge_driver_linux.c |   1 +
>  src/util/meson.build              |   1 +
>  src/util/viriptables.c            | 522 +--------------------------
>  src/util/viriptables.h            | 212 +++++------
>  src/util/virnetfilter.c           | 570 ++++++++++++++++++++++++++++++
>  src/util/virnetfilter.h           | 151 ++++++++
>  7 files changed, 849 insertions(+), 659 deletions(-)
>  create mode 100644 src/util/virnetfilter.c
>  create mode 100644 src/util/virnetfilter.h

If we move  'viriptables.{ch}' to 'src/network/bridge_iptables.{ch}
as first step in this series, then we would naturally also
have 'src/network/bridge_netfilter.{ch}' for this patch.

> 
> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> index 9f3868bbac..11b84a866a 100644
> --- a/src/libvirt_private.syms
> +++ b/src/libvirt_private.syms
> @@ -2550,30 +2550,6 @@ virInitctlSetRunLevel;
>  iptablesAddOutputFixUdpChecksum;
>  iptablesRemoveOutputFixUdpChecksum;
>  iptablesSetupPrivateChains;
> -virNetfilterAddDontMasquerade;
> -virNetfilterAddForwardAllowCross;
> -virNetfilterAddForwardAllowIn;
> -virNetfilterAddForwardAllowOut;
> -virNetfilterAddForwardAllowRelatedIn;
> -virNetfilterAddForwardMasquerade;
> -virNetfilterAddForwardRejectIn;
> -virNetfilterAddForwardRejectOut;
> -virNetfilterAddTcpInput;
> -virNetfilterAddTcpOutput;
> -virNetfilterAddUdpInput;
> -virNetfilterAddUdpOutput;
> -virNetfilterRemoveDontMasquerade;
> -virNetfilterRemoveForwardAllowCross;
> -virNetfilterRemoveForwardAllowIn;
> -virNetfilterRemoveForwardAllowOut;
> -virNetfilterRemoveForwardAllowRelatedIn;
> -virNetfilterRemoveForwardMasquerade;
> -virNetfilterRemoveForwardRejectIn;
> -virNetfilterRemoveForwardRejectOut;
> -virNetfilterRemoveTcpInput;
> -virNetfilterRemoveTcpOutput;
> -virNetfilterRemoveUdpInput;
> -virNetfilterRemoveUdpOutput;
>  
>  
>  # util/viriscsi.h
> @@ -2960,6 +2936,33 @@ virNetDevVPortProfileOpTypeFromString;
>  virNetDevVPortProfileOpTypeToString;
>  
>  
> +# util/virnetfilter.h
> +virNetfilterAddDontMasquerade;
> +virNetfilterAddForwardAllowCross;
> +virNetfilterAddForwardAllowIn;
> +virNetfilterAddForwardAllowOut;
> +virNetfilterAddForwardAllowRelatedIn;
> +virNetfilterAddForwardMasquerade;
> +virNetfilterAddForwardRejectIn;
> +virNetfilterAddForwardRejectOut;
> +virNetfilterAddTcpInput;
> +virNetfilterAddTcpOutput;
> +virNetfilterAddUdpInput;
> +virNetfilterAddUdpOutput;
> +virNetfilterRemoveDontMasquerade;
> +virNetfilterRemoveForwardAllowCross;
> +virNetfilterRemoveForwardAllowIn;
> +virNetfilterRemoveForwardAllowOut;
> +virNetfilterRemoveForwardAllowRelatedIn;
> +virNetfilterRemoveForwardMasquerade;
> +virNetfilterRemoveForwardRejectIn;
> +virNetfilterRemoveForwardRejectOut;
> +virNetfilterRemoveTcpInput;
> +virNetfilterRemoveTcpOutput;
> +virNetfilterRemoveUdpInput;
> +virNetfilterRemoveUdpOutput;
> +
> +
>  # util/virnetlink.h
>  virNetlinkCommand;
>  virNetlinkDelLink;
> diff --git a/src/network/bridge_driver_linux.c b/src/network/bridge_driver_linux.c
> index da7d78a40a..e03c17b259 100644
> --- a/src/network/bridge_driver_linux.c
> +++ b/src/network/bridge_driver_linux.c
> @@ -22,6 +22,7 @@
>  #include <config.h>
>  
>  #include "virfile.h"
> +#include "virnetfilter.h"
>  #include "viriptables.h"
>  #include "virstring.h"
>  #include "virlog.h"
> diff --git a/src/util/meson.build b/src/util/meson.build
> index c2175f1098..aa570ed02a 100644
> --- a/src/util/meson.build
> +++ b/src/util/meson.build
> @@ -69,6 +69,7 @@ util_sources = [
>    'virnetdevveth.c',
>    'virnetdevvlan.c',
>    'virnetdevvportprofile.c',
> +  'virnetfilter.c',
>    'virnetlink.c',
>    'virnodesuspend.c',
>    'virnuma.c',
> diff --git a/src/util/viriptables.c b/src/util/viriptables.c
> index 8db5bb3e4b..a85f3ea603 100644
> --- a/src/util/viriptables.c
> +++ b/src/util/viriptables.c
> @@ -27,6 +27,7 @@
>  #include <sys/stat.h>
>  
>  #include "internal.h"
> +#include "virnetfilter.h"
>  #include "viriptables.h"
>  #include "virfirewalld.h"
>  #include "virerror.h"
> @@ -37,11 +38,6 @@ VIR_LOG_INIT("util.iptables");
>  
>  #define VIR_FROM_THIS VIR_FROM_NONE
>  
> -enum {
> -    VIR_NETFILTER_INSERT = 0,
> -    VIR_NETFILTER_DELETE
> -};
> -
>  typedef struct {
>      const char *parent;
>      const char *child;
> @@ -155,7 +151,7 @@ iptablesSetupPrivateChains(virFirewallLayer layer)
>  }
>  
>  
> -static void
> +void
>  iptablesInput(virFirewall *fw,
>                virFirewallLayer layer,
>                const char *iface,
> @@ -176,7 +172,7 @@ iptablesInput(virFirewall *fw,
>                         NULL);
>  }
>  
> -static void
> +void
>  iptablesOutput(virFirewall *fw,
>                 virFirewallLayer layer,
>                 const char *iface,
> @@ -197,155 +193,11 @@ iptablesOutput(virFirewall *fw,
>                         NULL);
>  }
>  
> -/**
> - * virNetfilterAddTcpInput:
> - * @ctx: pointer to the IP table context
> - * @iface: the interface name
> - * @port: the TCP port to add
> - *
> - * Add an input to the IP table allowing access to the given @port on
> - * the given @iface interface for TCP packets
> - */
> -void
> -virNetfilterAddTcpInput(virFirewall *fw,
> -                        virFirewallLayer layer,
> -                        const char *iface,
> -                        int port)
> -{
> -    iptablesInput(fw, layer, iface, port, VIR_NETFILTER_INSERT, 1);
> -}
> -
> -/**
> - * virNetfilterRemoveTcpInput:
> - * @ctx: pointer to the IP table context
> - * @iface: the interface name
> - * @port: the TCP port to remove
> - *
> - * Removes an input from the IP table, hence forbidding access to the given
> - * @port on the given @iface interface for TCP packets
> - */
> -void
> -virNetfilterRemoveTcpInput(virFirewall *fw,
> -                           virFirewallLayer layer,
> -                           const char *iface,
> -                           int port)
> -{
> -    iptablesInput(fw, layer, iface, port, VIR_NETFILTER_DELETE, 1);
> -}
> -
> -/**
> - * virNetfilterAddUdpInput:
> - * @ctx: pointer to the IP table context
> - * @iface: the interface name
> - * @port: the UDP port to add
> - *
> - * Add an input to the IP table allowing access to the given @port on
> - * the given @iface interface for UDP packets
> - */
> -void
> -virNetfilterAddUdpInput(virFirewall *fw,
> -                        virFirewallLayer layer,
> -                        const char *iface,
> -                        int port)
> -{
> -    iptablesInput(fw, layer, iface, port, VIR_NETFILTER_INSERT, 0);
> -}
> -
> -/**
> - * virNetfilterRemoveUdpInput:
> - * @ctx: pointer to the IP table context
> - * @iface: the interface name
> - * @port: the UDP port to remove
> - *
> - * Removes an input from the IP table, hence forbidding access to the given
> - * @port on the given @iface interface for UDP packets
> - */
> -void
> -virNetfilterRemoveUdpInput(virFirewall *fw,
> -                           virFirewallLayer layer,
> -                           const char *iface,
> -                           int port)
> -{
> -    iptablesInput(fw, layer, iface, port, VIR_NETFILTER_DELETE, 0);
> -}
> -
> -/**
> - * virNetfilterAddTcpOutput:
> - * @ctx: pointer to the IP table context
> - * @iface: the interface name
> - * @port: the TCP port to add
> - *
> - * Add an output to the IP table allowing access to the given @port from
> - * the given @iface interface for TCP packets
> - */
> -void
> -virNetfilterAddTcpOutput(virFirewall *fw,
> -                         virFirewallLayer layer,
> -                         const char *iface,
> -                         int port)
> -{
> -    iptablesOutput(fw, layer, iface, port, VIR_NETFILTER_INSERT, 1);
> -}
> -
> -/**
> - * virNetfilterRemoveTcpOutput:
> - * @ctx: pointer to the IP table context
> - * @iface: the interface name
> - * @port: the UDP port to remove
> - *
> - * Removes an output from the IP table, hence forbidding access to the given
> - * @port from the given @iface interface for TCP packets
> - */
> -void
> -virNetfilterRemoveTcpOutput(virFirewall *fw,
> -                            virFirewallLayer layer,
> -                            const char *iface,
> -                            int port)
> -{
> -    iptablesOutput(fw, layer, iface, port, VIR_NETFILTER_DELETE, 1);
> -}
> -
> -/**
> - * virNetfilterAddUdpOutput:
> - * @ctx: pointer to the IP table context
> - * @iface: the interface name
> - * @port: the UDP port to add
> - *
> - * Add an output to the IP table allowing access to the given @port from
> - * the given @iface interface for UDP packets
> - */
> -void
> -virNetfilterAddUdpOutput(virFirewall *fw,
> -                         virFirewallLayer layer,
> -                         const char *iface,
> -                         int port)
> -{
> -    iptablesOutput(fw, layer, iface, port, VIR_NETFILTER_INSERT, 0);
> -}
> -
> -/**
> - * virNetfilterRemoveUdpOutput:
> - * @ctx: pointer to the IP table context
> - * @iface: the interface name
> - * @port: the UDP port to remove
> - *
> - * Removes an output from the IP table, hence forbidding access to the given
> - * @port from the given @iface interface for UDP packets
> - */
> -void
> -virNetfilterRemoveUdpOutput(virFirewall *fw,
> -                            virFirewallLayer layer,
> -                            const char *iface,
> -                            int port)
> -{
> -    iptablesOutput(fw, layer, iface, port, VIR_NETFILTER_DELETE, 0);
> -}
> -
>  
>  /* Allow all traffic coming from the bridge, with a valid network address
>   * to proceed to WAN
>   */
> -static int
> +int
>  iptablesForwardAllowOut(virFirewall *fw,
>                          virSocketAddr *netaddr,
>                          unsigned int prefix,
> @@ -383,59 +235,11 @@ iptablesForwardAllowOut(virFirewall *fw,
>      return 0;
>  }
>  
> -/**
> - * virNetfilterAddForwardAllowOut:
> - * @ctx: pointer to the IP table context
> - * @network: the source network name
> - * @iface: the source interface name
> - * @physdev: the physical output device
> - *
> - * Add a rule to the IP table context to allow the traffic for the
> - * network @network via interface @iface to be forwarded to
> - * @physdev device. This allow the outbound traffic on a bridge.
> - *
> - * Returns 0 in case of success or an error code otherwise
> - */
> -int
> -virNetfilterAddForwardAllowOut(virFirewall *fw,
> -                               virSocketAddr *netaddr,
> -                               unsigned int prefix,
> -                               const char *iface,
> -                               const char *physdev)
> -{
> -    return iptablesForwardAllowOut(fw, netaddr, prefix, iface, physdev,
> -                                   VIR_NETFILTER_INSERT);
> -}
> -
> -/**
> - * virNetfilterRemoveForwardAllowOut:
> - * @ctx: pointer to the IP table context
> - * @network: the source network name
> - * @iface: the source interface name
> - * @physdev: the physical output device
> - *
> - * Remove a rule from the IP table context hence forbidding forwarding
> - * of the traffic for the network @network via interface @iface
> - * to the @physdev device output. This stops the outbound traffic on a bridge.
> - *
> - * Returns 0 in case of success or an error code otherwise
> - */
> -int
> -virNetfilterRemoveForwardAllowOut(virFirewall *fw,
> -                                  virSocketAddr *netaddr,
> -                                  unsigned int prefix,
> -                                  const char *iface,
> -                                  const char *physdev)
> -{
> -    return iptablesForwardAllowOut(fw, netaddr, prefix, iface, physdev,
> -                                   VIR_NETFILTER_DELETE);
> -}
> -
>  
>  /* Allow all traffic destined to the bridge, with a valid network address
>   * and associated with an existing connection
>   */
> -static int
> +int
>  iptablesForwardAllowRelatedIn(virFirewall *fw,
>                                virSocketAddr *netaddr,
>                                unsigned int prefix,
> @@ -477,57 +281,10 @@ iptablesForwardAllowRelatedIn(virFirewall *fw,
>      return 0;
>  }
>  
> -/**
> - * virNetfilterAddForwardAllowRelatedIn:
> - * @ctx: pointer to the IP table context
> - * @network: the source network name
> - * @iface: the output interface name
> - * @physdev: the physical input device or NULL
> - *
> - * Add rules to the IP table context to allow the traffic for the
> - * network @network on @physdev device to be forwarded to
> - * interface @iface, if it is part of an existing connection.
> - *
> - * Returns 0 in case of success or an error code otherwise
> - */
> -int
> -virNetfilterAddForwardAllowRelatedIn(virFirewall *fw,
> -                                     virSocketAddr *netaddr,
> -                                     unsigned int prefix,
> -                                     const char *iface,
> -                                     const char *physdev)
> -{
> -    return iptablesForwardAllowRelatedIn(fw, netaddr, prefix, iface, physdev,
> -                                         VIR_NETFILTER_INSERT);
> -}
> -
> -/**
> - * virNetfilterRemoveForwardAllowRelatedIn:
> - * @ctx: pointer to the IP table context
> - * @network: the source network name
> - * @iface: the output interface name
> - * @physdev: the physical input device or NULL
> - *
> - * Remove rules from the IP table context hence forbidding the traffic for
> - * network @network on @physdev device to be forwarded to
> - * interface @iface, if it is part of an existing connection.
> - *
> - * Returns 0 in case of success or an error code otherwise
> - */
> -int
> -virNetfilterRemoveForwardAllowRelatedIn(virFirewall *fw,
> -                                        virSocketAddr *netaddr,
> -                                        unsigned int prefix,
> -                                        const char *iface,
> -                                        const char *physdev)
> -{
> -    return iptablesForwardAllowRelatedIn(fw, netaddr, prefix, iface, physdev,
> -                                         VIR_NETFILTER_DELETE);
> -}
>  
>  /* Allow all traffic destined to the bridge, with a valid network address
>   */
> -static int
> +int
>  iptablesForwardAllowIn(virFirewall *fw,
>                         virSocketAddr *netaddr,
>                         unsigned int prefix,
> @@ -564,55 +321,8 @@ iptablesForwardAllowIn(virFirewall *fw,
>      return 0;
>  }
>  
> -/**
> - * virNetfilterAddForwardAllowIn:
> - * @ctx: pointer to the IP table context
> - * @network: the source network name
> - * @iface: the output interface name
> - * @physdev: the physical input device or NULL
> - *
> - * Add rules to the IP table context to allow the traffic for the
> - * network @network on @physdev device to be forwarded to
> - * interface @iface. This allow the inbound traffic on a bridge.
> - *
> - * Returns 0 in case of success or an error code otherwise
> - */
> -int
> -virNetfilterAddForwardAllowIn(virFirewall *fw,
> -                              virSocketAddr *netaddr,
> -                              unsigned int prefix,
> -                              const char *iface,
> -                              const char *physdev)
> -{
> -    return iptablesForwardAllowIn(fw, netaddr, prefix, iface, physdev,
> -                                  VIR_NETFILTER_INSERT);
> -}
>  
> -/**
> - * virNetfilterRemoveForwardAllowIn:
> - * @ctx: pointer to the IP table context
> - * @network: the source network name
> - * @iface: the output interface name
> - * @physdev: the physical input device or NULL
> - *
> - * Remove rules from the IP table context hence forbidding the traffic for
> - * network @network on @physdev device to be forwarded to
> - * interface @iface. This stops the inbound traffic on a bridge.
> - *
> - * Returns 0 in case of success or an error code otherwise
> - */
> -int
> -virNetfilterRemoveForwardAllowIn(virFirewall *fw,
> -                                 virSocketAddr *netaddr,
> -                                 unsigned int prefix,
> -                                 const char *iface,
> -                                 const char *physdev)
> -{
> -    return iptablesForwardAllowIn(fw, netaddr, prefix, iface, physdev,
> -                                  VIR_NETFILTER_DELETE);
> -}
> -
> -static void
> +void
>  iptablesForwardAllowCross(virFirewall *fw,
>                            virFirewallLayer layer,
>                            const char *iface,
> @@ -628,45 +338,8 @@ iptablesForwardAllowCross(virFirewall *fw,
>                         NULL);
>  }
>  
> -/**
> - * virNetfilterAddForwardAllowCross:
> - * @ctx: pointer to the IP table context
> - * @iface: the input/output interface name
> - *
> - * Add rules to the IP table context to allow traffic to cross that
> - * interface. It allows all traffic between guests on the same bridge
> - * represented by that interface.
> - *
> - * Returns 0 in case of success or an error code otherwise
> - */
> -void
> -virNetfilterAddForwardAllowCross(virFirewall *fw,
> -                                 virFirewallLayer layer,
> -                                 const char *iface)
> -{
> -    iptablesForwardAllowCross(fw, layer, iface, VIR_NETFILTER_INSERT);
> -}
>  
> -/**
> - * virNetfilterRemoveForwardAllowCross:
> - * @ctx: pointer to the IP table context
> - * @iface: the input/output interface name
> - *
> - * Remove rules to the IP table context to block traffic to cross that
> - * interface. It forbids traffic between guests on the same bridge
> - * represented by that interface.
> - *
> - * Returns 0 in case of success or an error code otherwise
> - */
>  void
> -virNetfilterRemoveForwardAllowCross(virFirewall *fw,
> -                                    virFirewallLayer layer,
> -                                    const char *iface)
> -{
> -    iptablesForwardAllowCross(fw, layer, iface, VIR_NETFILTER_DELETE);
> -}
> -
> -static void
>  iptablesForwardRejectOut(virFirewall *fw,
>                           virFirewallLayer layer,
>                           const char *iface,
> @@ -681,44 +354,8 @@ iptablesForwardRejectOut(virFirewall *fw,
>                         NULL);
>  }
>  
> -/**
> - * virNetfilterAddForwardRejectOut:
> - * @ctx: pointer to the IP table context
> - * @iface: the output interface name
> - *
> - * Add rules to the IP table context to forbid all traffic to that
> - * interface. It forbids forwarding from the bridge to that interface.
> - *
> - * Returns 0 in case of success or an error code otherwise
> - */
> -void
> -virNetfilterAddForwardRejectOut(virFirewall *fw,
> -                                virFirewallLayer layer,
> -                                const char *iface)
> -{
> -    iptablesForwardRejectOut(fw, layer, iface, VIR_NETFILTER_INSERT);
> -}
>  
> -/**
> - * virNetfilterRemoveForwardRejectOut:
> - * @ctx: pointer to the IP table context
> - * @iface: the output interface name
> - *
> - * Remove rules from the IP table context forbidding all traffic to that
> - * interface. It reallow forwarding from the bridge to that interface.
> - *
> - * Returns 0 in case of success or an error code otherwise
> - */
>  void
> -virNetfilterRemoveForwardRejectOut(virFirewall *fw,
> -                                   virFirewallLayer layer,
> -                                   const char *iface)
> -{
> -    iptablesForwardRejectOut(fw, layer, iface, VIR_NETFILTER_DELETE);
> -}
> -
> -
> -static void
>  iptablesForwardRejectIn(virFirewall *fw,
>                          virFirewallLayer layer,
>                          const char *iface,
> @@ -733,47 +370,11 @@ iptablesForwardRejectIn(virFirewall *fw,
>                         NULL);
>  }
>  
> -/**
> - * virNetfilterAddForwardRejectIn:
> - * @ctx: pointer to the IP table context
> - * @iface: the input interface name
> - *
> - * Add rules to the IP table context to forbid all traffic from that
> - * interface. It forbids forwarding from that interface to the bridge.
> - *
> - * Returns 0 in case of success or an error code otherwise
> - */
> -void
> -virNetfilterAddForwardRejectIn(virFirewall *fw,
> -                               virFirewallLayer layer,
> -                               const char *iface)
> -{
> -    iptablesForwardRejectIn(fw, layer, iface, VIR_NETFILTER_INSERT);
> -}
> -
> -/**
> - * virNetfilterRemoveForwardRejectIn:
> - * @ctx: pointer to the IP table context
> - * @iface: the input interface name
> - *
> - * Remove rules from the IP table context forbidding all traffic from that
> - * interface. It allows forwarding from that interface to the bridge.
> - *
> - * Returns 0 in case of success or an error code otherwise
> - */
> -void
> -virNetfilterRemoveForwardRejectIn(virFirewall *fw,
> -                                  virFirewallLayer layer,
> -                                  const char *iface)
> -{
> -    iptablesForwardRejectIn(fw, layer, iface, VIR_NETFILTER_DELETE);
> -}
> -
>  
>  /* Masquerade all traffic coming from the network associated
>   * with the bridge
>   */
> -static int
> +int
>  iptablesForwardMasquerade(virFirewall *fw,
>                            virSocketAddr *netaddr,
>                            unsigned int prefix,
> @@ -868,65 +469,11 @@ iptablesForwardMasquerade(virFirewall *fw,
>      return 0;
>  }
>  
> -/**
> - * virNetfilterAddForwardMasquerade:
> - * @ctx: pointer to the IP table context
> - * @network: the source network name
> - * @physdev: the physical input device or NULL
> - * @protocol: the network protocol or NULL
> - *
> - * Add rules to the IP table context to allow masquerading
> - * network @network on @physdev. This allow the bridge to
> - * masquerade for that network (on @physdev).
> - *
> - * Returns 0 in case of success or an error code otherwise
> - */
> -int
> -virNetfilterAddForwardMasquerade(virFirewall *fw,
> -                                 virSocketAddr *netaddr,
> -                                 unsigned int prefix,
> -                                 const char *physdev,
> -                                 virSocketAddrRange *addr,
> -                                 virPortRange *port,
> -                                 const char *protocol)
> -{
> -    return iptablesForwardMasquerade(fw, netaddr, prefix,
> -                                     physdev, addr, port, protocol,
> -                                     VIR_NETFILTER_INSERT);
> -}
> -
> -/**
> - * virNetfilterRemoveForwardMasquerade:
> - * @ctx: pointer to the IP table context
> - * @network: the source network name
> - * @physdev: the physical input device or NULL
> - * @protocol: the network protocol or NULL
> - *
> - * Remove rules from the IP table context to stop masquerading
> - * network @network on @physdev. This stops the bridge from
> - * masquerading for that network (on @physdev).
> - *
> - * Returns 0 in case of success or an error code otherwise
> - */
> -int
> -virNetfilterRemoveForwardMasquerade(virFirewall *fw,
> -                                    virSocketAddr *netaddr,
> -                                    unsigned int prefix,
> -                                    const char *physdev,
> -                                    virSocketAddrRange *addr,
> -                                    virPortRange *port,
> -                                    const char *protocol)
> -{
> -    return iptablesForwardMasquerade(fw, netaddr, prefix,
> -                                     physdev, addr, port, protocol,
> -                                     VIR_NETFILTER_DELETE);
> -}
> -
>  
>  /* Don't masquerade traffic coming from the network associated with the bridge
>   * if said traffic targets @destaddr.
>   */
> -static int
> +int
>  iptablesForwardDontMasquerade(virFirewall *fw,
>                                virSocketAddr *netaddr,
>                                unsigned int prefix,
> @@ -964,57 +511,6 @@ iptablesForwardDontMasquerade(virFirewall *fw,
>      return 0;
>  }
>  
> -/**
> - * virNetfilterAddDontMasquerade:
> - * @netaddr: the source network name
> - * @prefix: prefix (# of 1 bits) of netmask to apply to @netaddr
> - * @physdev: the physical output device or NULL
> - * @destaddr: the destination network not to masquerade for
> - *
> - * Add rules to the IP table context to avoid masquerading from
> - * @netaddr/@prefix to @destaddr on @physdev. @destaddr must be in a format
> - * directly consumable by iptables/nftables, it must not depend on user input or
> - * configuration.
> - *
> - * Returns 0 in case of success or an error code otherwise.
> - */
> -int
> -virNetfilterAddDontMasquerade(virFirewall *fw,
> -                              virSocketAddr *netaddr,
> -                              unsigned int prefix,
> -                              const char *physdev,
> -                              const char *destaddr)
> -{
> -    return iptablesForwardDontMasquerade(fw, netaddr, prefix,
> -                                         physdev, destaddr, VIR_NETFILTER_INSERT);
> -}
> -
> -/**
> - * virNetfilterRemoveDontMasquerade:
> - * @netaddr: the source network name
> - * @prefix: prefix (# of 1 bits) of netmask to apply to @netaddr
> - * @physdev: the physical output device or NULL
> - * @destaddr: the destination network not to masquerade for
> - *
> - * Remove rules from the IP table context that prevent masquerading from
> - * @netaddr/@prefix to @destaddr on @physdev. @destaddr must be in a format
> - * directly consumable by iptables/nftables, it must not depend on user input or
> - * configuration.
> - *
> - * Returns 0 in case of success or an error code otherwise.
> - */
> -int
> -virNetfilterRemoveDontMasquerade(virFirewall *fw,
> -                                 virSocketAddr *netaddr,
> -                                 unsigned int prefix,
> -                                 const char *physdev,
> -                                 const char *destaddr)
> -{
> -    return iptablesForwardDontMasquerade(fw, netaddr, prefix,
> -                                         physdev, destaddr,
> -                                         VIR_NETFILTER_DELETE);
> -}
> -
>  
>  static void
>  iptablesOutputFixUdpChecksum(virFirewall *fw,
> diff --git a/src/util/viriptables.h b/src/util/viriptables.h
> index 610c4dccde..6ea589121e 100644
> --- a/src/util/viriptables.h
> +++ b/src/util/viriptables.h
> @@ -23,133 +23,101 @@
>  #include "virsocketaddr.h"
>  #include "virfirewall.h"
>  
> +/* These functions are (currently) called directly from the consumer
> + * (e.g. the network driver), and only when the iptables backend is
> + * selected. (Possibly/probably functions should be added to the
> + * netfilter*() API that will call them instead, but that first
> + * requires untangling all the special cases for setting up private
> + * chains that are necessitated by firewalld reloads).
> + */
>  int              iptablesSetupPrivateChains      (virFirewallLayer layer);
>  
> -void             virNetfilterAddTcpInput         (virFirewall *fw,
> -                                                  virFirewallLayer layer,
> -                                                  const char *iface,
> -                                                  int port);
> -void             virNetfilterRemoveTcpInput      (virFirewall *fw,
> -                                                  virFirewallLayer layer,
> -                                                  const char *iface,
> -                                                  int port);
> -
> -void             virNetfilterAddUdpInput         (virFirewall *fw,
> -                                                  virFirewallLayer layer,
> -                                                  const char *iface,
> -                                                  int port);
> -void             virNetfilterRemoveUdpInput      (virFirewall *fw,
> -                                                  virFirewallLayer layer,
> -                                                  const char *iface,
> -                                                  int port);
> -
> -void             virNetfilterAddTcpOutput        (virFirewall *fw,
> -                                                  virFirewallLayer layer,
> -                                                  const char *iface,
> -                                                  int port);
> -void             virNetfilterRemoveTcpOutput     (virFirewall *fw,
> -                                                  virFirewallLayer layer,
> -                                                  const char *iface,
> -                                                  int port);
> -void             virNetfilterAddUdpOutput        (virFirewall *fw,
> -                                                  virFirewallLayer layer,
> -                                                  const char *iface,
> -                                                  int port);
> -void             virNetfilterRemoveUdpOutput     (virFirewall *fw,
> -                                                  virFirewallLayer layer,
> -                                                  const char *iface,
> -                                                  int port);
> -
> -int              virNetfilterAddForwardAllowOut  (virFirewall *fw,
> -                                                  virSocketAddr *netaddr,
> -                                                  unsigned int prefix,
> -                                                  const char *iface,
> -                                                  const char *physdev)
> -    G_GNUC_WARN_UNUSED_RESULT;
> -int              virNetfilterRemoveForwardAllowOut(virFirewall *fw,
> -                                                   virSocketAddr *netaddr,
> -                                                   unsigned int prefix,
> -                                                   const char *iface,
> -                                                   const char *physdev)
> -    G_GNUC_WARN_UNUSED_RESULT;
> -int              virNetfilterAddForwardAllowRelatedIn(virFirewall *fw,
> -                                                      virSocketAddr *netaddr,
> -                                                      unsigned int prefix,
> -                                                      const char *iface,
> -                                                      const char *physdev)
> -    G_GNUC_WARN_UNUSED_RESULT;
> -int              virNetfilterRemoveForwardAllowRelatedIn(virFirewall *fw,
> -                                                         virSocketAddr *netaddr,
> -                                                         unsigned int prefix,
> -                                                         const char *iface,
> -                                                         const char *physdev)
> -    G_GNUC_WARN_UNUSED_RESULT;
> -
> -int              virNetfilterAddForwardAllowIn   (virFirewall *fw,
> -                                                  virSocketAddr *netaddr,
> -                                                  unsigned int prefix,
> -                                                  const char *iface,
> -                                                  const char *physdev)
> -    G_GNUC_WARN_UNUSED_RESULT;
> -int              virNetfilterRemoveForwardAllowIn(virFirewall *fw,
> -                                                  virSocketAddr *netaddr,
> -                                                  unsigned int prefix,
> -                                                  const char *iface,
> -                                                  const char *physdev)
> -    G_GNUC_WARN_UNUSED_RESULT;
> -
> -void             virNetfilterAddForwardAllowCross(virFirewall *fw,
> -                                                  virFirewallLayer layer,
> -                                                  const char *iface);
> -void             virNetfilterRemoveForwardAllowCross(virFirewall *fw,
> -                                                     virFirewallLayer layer,
> -                                                     const char *iface);
> -
> -void             virNetfilterAddForwardRejectOut (virFirewall *fw,
> -                                                  virFirewallLayer layer,
> -                                                  const char *iface);
> -void             virNetfilterRemoveForwardRejectOut(virFirewall *fw,
> -                                                    virFirewallLayer layer,
> -                                                    const char *iface);
> -
> -void             virNetfilterAddForwardRejectIn  (virFirewall *fw,
> -                                                  virFirewallLayer layer,
> -                                                  const char *iface);
> -void             virNetfilterRemoveForwardRejectIn(virFirewall *fw,
> -                                                   virFirewallLayer layery,
> -                                                   const char *iface);
> -
> -int              virNetfilterAddForwardMasquerade(virFirewall *fw,
> -                                                  virSocketAddr *netaddr,
> -                                                  unsigned int prefix,
> -                                                  const char *physdev,
> -                                                  virSocketAddrRange *addr,
> -                                                  virPortRange *port,
> -                                                  const char *protocol)
> -    G_GNUC_WARN_UNUSED_RESULT;
> -int              virNetfilterRemoveForwardMasquerade(virFirewall *fw,
> -                                                     virSocketAddr *netaddr,
> -                                                     unsigned int prefix,
> -                                                     const char *physdev,
> -                                                     virSocketAddrRange *addr,
> -                                                     virPortRange *port,
> -                                                     const char *protocol)
> -    G_GNUC_WARN_UNUSED_RESULT;
> -int              virNetfilterAddDontMasquerade   (virFirewall *fw,
> -                                                  virSocketAddr *netaddr,
> -                                                  unsigned int prefix,
> -                                                  const char *physdev,
> -                                                  const char *destaddr)
> -    G_GNUC_WARN_UNUSED_RESULT;
> -int              virNetfilterRemoveDontMasquerade(virFirewall *fw,
> -                                                  virSocketAddr *netaddr,
> -                                                  unsigned int prefix,
> -                                                  const char *physdev,
> -                                                  const char *destaddr)
> -    G_GNUC_WARN_UNUSED_RESULT;
>  void             iptablesAddOutputFixUdpChecksum (virFirewall *fw,
>                                                    const char *iface,
>                                                    int port);
>  void             iptablesRemoveOutputFixUdpChecksum (virFirewall *fw,
>                                                       const char *iface,
>                                                       int port);
> +
> +/* These functions are only called from virnetfilter.c. Each can be
> + * called with an action of VIR_NETFILTER_INSERT or
> + * VIR_NETFILTER_DELETE, to add or remove the described rule(s) in the
> + * appropriate chain.
> + */
> +
> +void
> +iptablesInput(virFirewall *fw,
> +              virFirewallLayer layer,
> +              const char *iface,
> +              int port,
> +              int action,
> +              int tcp);
> +
> +void
> +iptablesOutput(virFirewall *fw,
> +               virFirewallLayer layer,
> +               const char *iface,
> +               int port,
> +               int action,
> +               int tcp);
> +
> +int
> +iptablesForwardAllowOut(virFirewall *fw,
> +                        virSocketAddr *netaddr,
> +                        unsigned int prefix,
> +                        const char *iface,
> +                        const char *physdev,
> +                        int action);
> +
> +int
> +iptablesForwardAllowRelatedIn(virFirewall *fw,
> +                              virSocketAddr *netaddr,
> +                              unsigned int prefix,
> +                              const char *iface,
> +                              const char *physdev,
> +                              int action);
> +
> +int
> +iptablesForwardAllowIn(virFirewall *fw,
> +                       virSocketAddr *netaddr,
> +                       unsigned int prefix,
> +                       const char *iface,
> +                       const char *physdev,
> +                       int action);
> +
> +
> +void
> +iptablesForwardAllowCross(virFirewall *fw,
> +                          virFirewallLayer layer,
> +                          const char *iface,
> +                          int action);
> +
> +void
> +iptablesForwardRejectOut(virFirewall *fw,
> +                         virFirewallLayer layer,
> +                         const char *iface,
> +                         int action);
> +
> +void
> +iptablesForwardRejectIn(virFirewall *fw,
> +                        virFirewallLayer layer,
> +                        const char *iface,
> +                        int action);
> +
> +int
> +iptablesForwardMasquerade(virFirewall *fw,
> +                          virSocketAddr *netaddr,
> +                          unsigned int prefix,
> +                          const char *physdev,
> +                          virSocketAddrRange *addr,
> +                          virPortRange *port,
> +                          const char *protocol,
> +                          int action);
> +
> +int
> +iptablesForwardDontMasquerade(virFirewall *fw,
> +                              virSocketAddr *netaddr,
> +                              unsigned int prefix,
> +                              const char *physdev,
> +                              const char *destaddr,
> +                              int action);
> diff --git a/src/util/virnetfilter.c b/src/util/virnetfilter.c
> new file mode 100644
> index 0000000000..efe2ca01dc
> --- /dev/null
> +++ b/src/util/virnetfilter.c
> @@ -0,0 +1,570 @@
> +/*
> + * virnetfilter.c: backend-agnostic packet filter helper APIs
> + *
> + * Copyright (C) 2023 Red Hat, Inc.
> + *
> + * 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 <stdarg.h>
> +#include <unistd.h>
> +#include <fcntl.h>
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +
> +#include "internal.h"
> +#include "virnetfilter.h"
> +#include "viriptables.h"
> +#include "vircommand.h"
> +#include "viralloc.h"
> +#include "virerror.h"
> +#include "virfile.h"
> +#include "virlog.h"
> +#include "virthread.h"
> +#include "virstring.h"
> +#include "virutil.h"
> +#include "virhash.h"
> +
> +VIR_LOG_INIT("util.netfilter");
> +
> +#define VIR_FROM_THIS VIR_FROM_NONE
> +
> +
> +/**
> + * virNetfilterAddTcpInput:
> + * @ctx: pointer to the IP table context
> + * @iface: the interface name
> + * @port: the TCP port to add
> + *
> + * Add an input to the IP table allowing access to the given @port on
> + * the given @iface interface for TCP packets
> + */
> +void
> +virNetfilterAddTcpInput(virFirewall *fw,
> +                        virFirewallLayer layer,
> +                        const char *iface,
> +                        int port)
> +{
> +    iptablesInput(fw, layer, iface, port, VIR_NETFILTER_INSERT, 1);
> +}
> +
> +
> +/**
> + * virNetfilterRemoveTcpInput:
> + * @ctx: pointer to the IP table context
> + * @iface: the interface name
> + * @port: the TCP port to remove
> + *
> + * Removes an input from the IP table, hence forbidding access to the given
> + * @port on the given @iface interface for TCP packets
> + */
> +void
> +virNetfilterRemoveTcpInput(virFirewall *fw,
> +                           virFirewallLayer layer,
> +                           const char *iface,
> +                           int port)
> +{
> +    iptablesInput(fw, layer, iface, port, VIR_NETFILTER_DELETE, 1);
> +}
> +
> +
> +/**
> + * virNetfilterAddUdpInput:
> + * @ctx: pointer to the IP table context
> + * @iface: the interface name
> + * @port: the UDP port to add
> + *
> + * Add an input to the IP table allowing access to the given @port on
> + * the given @iface interface for UDP packets
> + */
> +void
> +virNetfilterAddUdpInput(virFirewall *fw,
> +                        virFirewallLayer layer,
> +                        const char *iface,
> +                        int port)
> +{
> +    iptablesInput(fw, layer, iface, port, VIR_NETFILTER_INSERT, 0);
> +}
> +
> +
> +/**
> + * virNetfilterRemoveUdpInput:
> + * @ctx: pointer to the IP table context
> + * @iface: the interface name
> + * @port: the UDP port to remove
> + *
> + * Removes an input from the IP table, hence forbidding access to the given
> + * @port on the given @iface interface for UDP packets
> + */
> +void
> +virNetfilterRemoveUdpInput(virFirewall *fw,
> +                           virFirewallLayer layer,
> +                           const char *iface,
> +                           int port)
> +{
> +    iptablesInput(fw, layer, iface, port, VIR_NETFILTER_DELETE, 0);
> +}
> +
> +
> +/**
> + * virNetfilterAddTcpOutput:
> + * @ctx: pointer to the IP table context
> + * @iface: the interface name
> + * @port: the TCP port to add
> + *
> + * Add an output to the IP table allowing access to the given @port from
> + * the given @iface interface for TCP packets
> + */
> +void
> +virNetfilterAddTcpOutput(virFirewall *fw,
> +                         virFirewallLayer layer,
> +                         const char *iface,
> +                         int port)
> +{
> +    iptablesOutput(fw, layer, iface, port, VIR_NETFILTER_INSERT, 1);
> +}
> +
> +
> +/**
> + * virNetfilterRemoveTcpOutput:
> + * @ctx: pointer to the IP table context
> + * @iface: the interface name
> + * @port: the UDP port to remove
> + *
> + * Removes an output from the IP table, hence forbidding access to the given
> + * @port from the given @iface interface for TCP packets
> + */
> +void
> +virNetfilterRemoveTcpOutput(virFirewall *fw,
> +                            virFirewallLayer layer,
> +                            const char *iface,
> +                            int port)
> +{
> +    iptablesOutput(fw, layer, iface, port, VIR_NETFILTER_DELETE, 1);
> +}
> +
> +
> +/**
> + * virNetfilterAddUdpOutput:
> + * @ctx: pointer to the IP table context
> + * @iface: the interface name
> + * @port: the UDP port to add
> + *
> + * Add an output to the IP table allowing access to the given @port from
> + * the given @iface interface for UDP packets
> + */
> +void
> +virNetfilterAddUdpOutput(virFirewall *fw,
> +                         virFirewallLayer layer,
> +                         const char *iface,
> +                         int port)
> +{
> +    iptablesOutput(fw, layer, iface, port, VIR_NETFILTER_INSERT, 0);
> +}
> +
> +
> +/**
> + * virNetfilterRemoveUdpOutput:
> + * @ctx: pointer to the IP table context
> + * @iface: the interface name
> + * @port: the UDP port to remove
> + *
> + * Removes an output from the IP table, hence forbidding access to the given
> + * @port from the given @iface interface for UDP packets
> + */
> +void
> +virNetfilterRemoveUdpOutput(virFirewall *fw,
> +                            virFirewallLayer layer,
> +                            const char *iface,
> +                            int port)
> +{
> +    iptablesOutput(fw, layer, iface, port, VIR_NETFILTER_DELETE, 0);
> +}
> +
> +
> +/**
> + * virNetfilterAddForwardAllowOut:
> + * @ctx: pointer to the IP table context
> + * @network: the source network name
> + * @iface: the source interface name
> + * @physdev: the physical output device
> + *
> + * Add a rule to the IP table context to allow the traffic for the
> + * network @network via interface @iface to be forwarded to
> + * @physdev device. This allow the outbound traffic on a bridge.
> + *
> + * Returns 0 in case of success or an error code otherwise
> + */
> +int
> +virNetfilterAddForwardAllowOut(virFirewall *fw,
> +                               virSocketAddr *netaddr,
> +                               unsigned int prefix,
> +                               const char *iface,
> +                               const char *physdev)
> +{
> +    return iptablesForwardAllowOut(fw, netaddr, prefix, iface, physdev,
> +                                   VIR_NETFILTER_INSERT);
> +}
> +
> +
> +/**
> + * virNetfilterRemoveForwardAllowOut:
> + * @ctx: pointer to the IP table context
> + * @network: the source network name
> + * @iface: the source interface name
> + * @physdev: the physical output device
> + *
> + * Remove a rule from the IP table context hence forbidding forwarding
> + * of the traffic for the network @network via interface @iface
> + * to the @physdev device output. This stops the outbound traffic on a bridge.
> + *
> + * Returns 0 in case of success or an error code otherwise
> + */
> +int
> +virNetfilterRemoveForwardAllowOut(virFirewall *fw,
> +                                  virSocketAddr *netaddr,
> +                                  unsigned int prefix,
> +                                  const char *iface,
> +                                  const char *physdev)
> +{
> +    return iptablesForwardAllowOut(fw, netaddr, prefix, iface, physdev,
> +                                   VIR_NETFILTER_DELETE);
> +}
> +
> +
> +/**
> + * virNetfilterAddForwardAllowRelatedIn:
> + * @ctx: pointer to the IP table context
> + * @network: the source network name
> + * @iface: the output interface name
> + * @physdev: the physical input device or NULL
> + *
> + * Add rules to the IP table context to allow the traffic for the
> + * network @network on @physdev device to be forwarded to
> + * interface @iface, if it is part of an existing connection.
> + *
> + * Returns 0 in case of success or an error code otherwise
> + */
> +int
> +virNetfilterAddForwardAllowRelatedIn(virFirewall *fw,
> +                                     virSocketAddr *netaddr,
> +                                     unsigned int prefix,
> +                                     const char *iface,
> +                                     const char *physdev)
> +{
> +    return iptablesForwardAllowRelatedIn(fw, netaddr, prefix, iface, physdev,
> +                                         VIR_NETFILTER_INSERT);
> +}
> +
> +
> +/**
> + * virNetfilterRemoveForwardAllowRelatedIn:
> + * @ctx: pointer to the IP table context
> + * @network: the source network name
> + * @iface: the output interface name
> + * @physdev: the physical input device or NULL
> + *
> + * Remove rules from the IP table context hence forbidding the traffic for
> + * network @network on @physdev device to be forwarded to
> + * interface @iface, if it is part of an existing connection.
> + *
> + * Returns 0 in case of success or an error code otherwise
> + */
> +int
> +virNetfilterRemoveForwardAllowRelatedIn(virFirewall *fw,
> +                                        virSocketAddr *netaddr,
> +                                        unsigned int prefix,
> +                                        const char *iface,
> +                                        const char *physdev)
> +{
> +    return iptablesForwardAllowRelatedIn(fw, netaddr, prefix, iface, physdev,
> +                                         VIR_NETFILTER_DELETE);
> +}
> +
> +
> +/**
> + * virNetfilterAddForwardAllowIn:
> + * @ctx: pointer to the IP table context
> + * @network: the source network name
> + * @iface: the output interface name
> + * @physdev: the physical input device or NULL
> + *
> + * Add rules to the IP table context to allow the traffic for the
> + * network @network on @physdev device to be forwarded to
> + * interface @iface. This allow the inbound traffic on a bridge.
> + *
> + * Returns 0 in case of success or an error code otherwise
> + */
> +int
> +virNetfilterAddForwardAllowIn(virFirewall *fw,
> +                              virSocketAddr *netaddr,
> +                              unsigned int prefix,
> +                              const char *iface,
> +                              const char *physdev)
> +{
> +    return iptablesForwardAllowIn(fw, netaddr, prefix, iface, physdev,
> +                                  VIR_NETFILTER_INSERT);
> +}
> +
> +
> +/**
> + * virNetfilterRemoveForwardAllowIn:
> + * @ctx: pointer to the IP table context
> + * @network: the source network name
> + * @iface: the output interface name
> + * @physdev: the physical input device or NULL
> + *
> + * Remove rules from the IP table context hence forbidding the traffic for
> + * network @network on @physdev device to be forwarded to
> + * interface @iface. This stops the inbound traffic on a bridge.
> + *
> + * Returns 0 in case of success or an error code otherwise
> + */
> +int
> +virNetfilterRemoveForwardAllowIn(virFirewall *fw,
> +                                 virSocketAddr *netaddr,
> +                                 unsigned int prefix,
> +                                 const char *iface,
> +                                 const char *physdev)
> +{
> +    return iptablesForwardAllowIn(fw, netaddr, prefix, iface, physdev,
> +                                  VIR_NETFILTER_DELETE);
> +}
> +
> +
> +/**
> + * virNetfilterAddForwardAllowCross:
> + * @ctx: pointer to the IP table context
> + * @iface: the input/output interface name
> + *
> + * Add rules to the IP table context to allow traffic to cross that
> + * interface. It allows all traffic between guests on the same bridge
> + * represented by that interface.
> + *
> + * Returns 0 in case of success or an error code otherwise
> + */
> +void
> +virNetfilterAddForwardAllowCross(virFirewall *fw,
> +                                 virFirewallLayer layer,
> +                                 const char *iface)
> +{
> +    iptablesForwardAllowCross(fw, layer, iface, VIR_NETFILTER_INSERT);
> +}
> +
> +
> +/**
> + * virNetfilterRemoveForwardAllowCross:
> + * @ctx: pointer to the IP table context
> + * @iface: the input/output interface name
> + *
> + * Remove rules to the IP table context to block traffic to cross that
> + * interface. It forbids traffic between guests on the same bridge
> + * represented by that interface.
> + *
> + * Returns 0 in case of success or an error code otherwise
> + */
> +void
> +virNetfilterRemoveForwardAllowCross(virFirewall *fw,
> +                                    virFirewallLayer layer,
> +                                    const char *iface)
> +{
> +    iptablesForwardAllowCross(fw, layer, iface, VIR_NETFILTER_DELETE);
> +}
> +
> +
> +/**
> + * virNetfilterAddForwardRejectOut:
> + * @ctx: pointer to the IP table context
> + * @iface: the output interface name
> + *
> + * Add rules to the IP table context to forbid all traffic to that
> + * interface. It forbids forwarding from the bridge to that interface.
> + *
> + * Returns 0 in case of success or an error code otherwise
> + */
> +void
> +virNetfilterAddForwardRejectOut(virFirewall *fw,
> +                                virFirewallLayer layer,
> +                                const char *iface)
> +{
> +    iptablesForwardRejectOut(fw, layer, iface, VIR_NETFILTER_INSERT);
> +}
> +
> +/**
> + * virNetfilterRemoveForwardRejectOut:
> + * @ctx: pointer to the IP table context
> + * @iface: the output interface name
> + *
> + * Remove rules from the IP table context forbidding all traffic to that
> + * interface. It reallow forwarding from the bridge to that interface.
> + *
> + * Returns 0 in case of success or an error code otherwise
> + */
> +void
> +virNetfilterRemoveForwardRejectOut(virFirewall *fw,
> +                                   virFirewallLayer layer,
> +                                   const char *iface)
> +{
> +    iptablesForwardRejectOut(fw, layer, iface, VIR_NETFILTER_DELETE);
> +}
> +
> +
> +/**
> + * virNetfilterAddForwardRejectIn:
> + * @ctx: pointer to the IP table context
> + * @iface: the input interface name
> + *
> + * Add rules to the IP table context to forbid all traffic from that
> + * interface. It forbids forwarding from that interface to the bridge.
> + *
> + * Returns 0 in case of success or an error code otherwise
> + */
> +void
> +virNetfilterAddForwardRejectIn(virFirewall *fw,
> +                               virFirewallLayer layer,
> +                               const char *iface)
> +{
> +    iptablesForwardRejectIn(fw, layer, iface, VIR_NETFILTER_INSERT);
> +}
> +
> +
> +/**
> + * virNetfilterRemoveForwardRejectIn:
> + * @ctx: pointer to the IP table context
> + * @iface: the input interface name
> + *
> + * Remove rules from the IP table context forbidding all traffic from that
> + * interface. It allows forwarding from that interface to the bridge.
> + *
> + * Returns 0 in case of success or an error code otherwise
> + */
> +void
> +virNetfilterRemoveForwardRejectIn(virFirewall *fw,
> +                                  virFirewallLayer layer,
> +                                  const char *iface)
> +{
> +    iptablesForwardRejectIn(fw, layer, iface, VIR_NETFILTER_DELETE);
> +}
> +
> +
> +/**
> + * virNetfilterAddForwardMasquerade:
> + * @ctx: pointer to the IP table context
> + * @network: the source network name
> + * @physdev: the physical input device or NULL
> + * @protocol: the network protocol or NULL
> + *
> + * Add rules to the IP table context to allow masquerading
> + * network @network on @physdev. This allow the bridge to
> + * masquerade for that network (on @physdev).
> + *
> + * Returns 0 in case of success or an error code otherwise
> + */
> +int
> +virNetfilterAddForwardMasquerade(virFirewall *fw,
> +                                 virSocketAddr *netaddr,
> +                                 unsigned int prefix,
> +                                 const char *physdev,
> +                                 virSocketAddrRange *addr,
> +                                 virPortRange *port,
> +                                 const char *protocol)
> +{
> +    return iptablesForwardMasquerade(fw, netaddr, prefix,
> +                                     physdev, addr, port, protocol,
> +                                     VIR_NETFILTER_INSERT);
> +}
> +
> +
> +/**
> + * virNetfilterRemoveForwardMasquerade:
> + * @ctx: pointer to the IP table context
> + * @network: the source network name
> + * @physdev: the physical input device or NULL
> + * @protocol: the network protocol or NULL
> + *
> + * Remove rules from the IP table context to stop masquerading
> + * network @network on @physdev. This stops the bridge from
> + * masquerading for that network (on @physdev).
> + *
> + * Returns 0 in case of success or an error code otherwise
> + */
> +int
> +virNetfilterRemoveForwardMasquerade(virFirewall *fw,
> +                                    virSocketAddr *netaddr,
> +                                    unsigned int prefix,
> +                                    const char *physdev,
> +                                    virSocketAddrRange *addr,
> +                                    virPortRange *port,
> +                                    const char *protocol)
> +{
> +    return iptablesForwardMasquerade(fw, netaddr, prefix,
> +                                     physdev, addr, port, protocol,
> +                                     VIR_NETFILTER_DELETE);
> +}
> +
> +
> +/**
> + * virNetfilterAddDontMasquerade:
> + * @netaddr: the source network name
> + * @prefix: prefix (# of 1 bits) of netmask to apply to @netaddr
> + * @physdev: the physical output device or NULL
> + * @destaddr: the destination network not to masquerade for
> + *
> + * Add rules to the IP table context to avoid masquerading from
> + * @netaddr/@prefix to @destaddr on @physdev. @destaddr must be in a format
> + * directly consumable by iptables/nftables, it must not depend on user input or
> + * configuration.
> + *
> + * Returns 0 in case of success or an error code otherwise.
> + */
> +int
> +virNetfilterAddDontMasquerade(virFirewall *fw,
> +                              virSocketAddr *netaddr,
> +                              unsigned int prefix,
> +                              const char *physdev,
> +                              const char *destaddr)
> +{
> +    return iptablesForwardDontMasquerade(fw, netaddr, prefix,
> +                                         physdev, destaddr, VIR_NETFILTER_INSERT);
> +}
> +
> +
> +/**
> + * virNetfilterRemoveDontMasquerade:
> + * @netaddr: the source network name
> + * @prefix: prefix (# of 1 bits) of netmask to apply to @netaddr
> + * @physdev: the physical output device or NULL
> + * @destaddr: the destination network not to masquerade for
> + *
> + * Remove rules from the IP table context that prevent masquerading from
> + * @netaddr/@prefix to @destaddr on @physdev. @destaddr must be in a format
> + * directly consumable by iptables/nftables, it must not depend on user input or
> + * configuration.
> + *
> + * Returns 0 in case of success or an error code otherwise.
> + */
> +int
> +virNetfilterRemoveDontMasquerade(virFirewall *fw,
> +                                 virSocketAddr *netaddr,
> +                                 unsigned int prefix,
> +                                 const char *physdev,
> +                                 const char *destaddr)
> +{
> +    return iptablesForwardDontMasquerade(fw, netaddr, prefix,
> +                                         physdev, destaddr,
> +                                         VIR_NETFILTER_DELETE);
> +}
> diff --git a/src/util/virnetfilter.h b/src/util/virnetfilter.h
> new file mode 100644
> index 0000000000..c75f7eccbd
> --- /dev/null
> +++ b/src/util/virnetfilter.h
> @@ -0,0 +1,151 @@
> +/*
> + * virnetfilter.h: backend-agnostic packet filter helper APIs
> + *
> + * Copyright (C) 2023 Red Hat, Inc.
> + *
> + * 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 "virsocketaddr.h"
> +#include "virfirewall.h"
> +
> +enum {
> +    VIR_NETFILTER_INSERT = 0,
> +    VIR_NETFILTER_DELETE
> +};
> +
> +void             virNetfilterAddTcpInput         (virFirewall *fw,
> +                                                  virFirewallLayer layer,
> +                                                  const char *iface,
> +                                                  int port);
> +void             virNetfilterRemoveTcpInput      (virFirewall *fw,
> +                                                  virFirewallLayer layer,
> +                                                  const char *iface,
> +                                                  int port);
> +void             virNetfilterAddUdpInput         (virFirewall *fw,
> +                                                  virFirewallLayer layer,
> +                                                  const char *iface,
> +                                                  int port);
> +void             virNetfilterRemoveUdpInput      (virFirewall *fw,
> +                                                  virFirewallLayer layer,
> +                                                  const char *iface,
> +                                                  int port);
> +
> +void             virNetfilterAddTcpOutput        (virFirewall *fw,
> +                                                  virFirewallLayer layer,
> +                                                  const char *iface,
> +                                                  int port);
> +void             virNetfilterRemoveTcpOutput     (virFirewall *fw,
> +                                                  virFirewallLayer layer,
> +                                                  const char *iface,
> +                                                  int port);
> +void             virNetfilterAddUdpOutput        (virFirewall *fw,
> +                                                  virFirewallLayer layer,
> +                                                  const char *iface,
> +                                                  int port);
> +void             virNetfilterRemoveUdpOutput     (virFirewall *fw,
> +                                                  virFirewallLayer layer,
> +                                                  const char *iface,
> +                                                  int port);
> +
> +int              virNetfilterAddForwardAllowOut  (virFirewall *fw,
> +                                                  virSocketAddr *netaddr,
> +                                                  unsigned int prefix,
> +                                                  const char *iface,
> +                                                  const char *physdev)
> +    G_GNUC_WARN_UNUSED_RESULT;
> +int              virNetfilterRemoveForwardAllowOut(virFirewall *fw,
> +                                                   virSocketAddr *netaddr,
> +                                                   unsigned int prefix,
> +                                                   const char *iface,
> +                                                   const char *physdev)
> +    G_GNUC_WARN_UNUSED_RESULT;
> +int              virNetfilterAddForwardAllowRelatedIn(virFirewall *fw,
> +                                                      virSocketAddr *netaddr,
> +                                                      unsigned int prefix,
> +                                                      const char *iface,
> +                                                      const char *physdev)
> +    G_GNUC_WARN_UNUSED_RESULT;
> +int              virNetfilterRemoveForwardAllowRelatedIn(virFirewall *fw,
> +                                                         virSocketAddr *netaddr,
> +                                                         unsigned int prefix,
> +                                                         const char *iface,
> +                                                         const char *physdev)
> +    G_GNUC_WARN_UNUSED_RESULT;
> +
> +int              virNetfilterAddForwardAllowIn   (virFirewall *fw,
> +                                                  virSocketAddr *netaddr,
> +                                                  unsigned int prefix,
> +                                                  const char *iface,
> +                                                  const char *physdev)
> +    G_GNUC_WARN_UNUSED_RESULT;
> +int              virNetfilterRemoveForwardAllowIn(virFirewall *fw,
> +                                                  virSocketAddr *netaddr,
> +                                                  unsigned int prefix,
> +                                                  const char *iface,
> +                                                  const char *physdev)
> +    G_GNUC_WARN_UNUSED_RESULT;
> +
> +void             virNetfilterAddForwardAllowCross(virFirewall *fw,
> +                                                  virFirewallLayer layer,
> +                                                  const char *iface);
> +void             virNetfilterRemoveForwardAllowCross(virFirewall *fw,
> +                                                     virFirewallLayer layer,
> +                                                     const char *iface);
> +
> +void             virNetfilterAddForwardRejectOut (virFirewall *fw,
> +                                                  virFirewallLayer layer,
> +                                                  const char *iface);
> +void             virNetfilterRemoveForwardRejectOut(virFirewall *fw,
> +                                                    virFirewallLayer layer,
> +                                                    const char *iface);
> +
> +void             virNetfilterAddForwardRejectIn  (virFirewall *fw,
> +                                                  virFirewallLayer layer,
> +                                                  const char *iface);
> +void             virNetfilterRemoveForwardRejectIn(virFirewall *fw,
> +                                                   virFirewallLayer layery,
> +                                                   const char *iface);
> +
> +int              virNetfilterAddForwardMasquerade(virFirewall *fw,
> +                                                  virSocketAddr *netaddr,
> +                                                  unsigned int prefix,
> +                                                  const char *physdev,
> +                                                  virSocketAddrRange *addr,
> +                                                  virPortRange *port,
> +                                                  const char *protocol)
> +    G_GNUC_WARN_UNUSED_RESULT;
> +int              virNetfilterRemoveForwardMasquerade(virFirewall *fw,
> +                                                     virSocketAddr *netaddr,
> +                                                     unsigned int prefix,
> +                                                     const char *physdev,
> +                                                     virSocketAddrRange *addr,
> +                                                     virPortRange *port,
> +                                                     const char *protocol)
> +    G_GNUC_WARN_UNUSED_RESULT;
> +int              virNetfilterAddDontMasquerade   (virFirewall *fw,
> +                                                  virSocketAddr *netaddr,
> +                                                  unsigned int prefix,
> +                                                  const char *physdev,
> +                                                  const char *destaddr)
> +    G_GNUC_WARN_UNUSED_RESULT;
> +int              virNetfilterRemoveDontMasquerade(virFirewall *fw,
> +                                                  virSocketAddr *netaddr,
> +                                                  unsigned int prefix,
> +                                                  const char *physdev,
> +                                                  const char *destaddr)
> +    G_GNUC_WARN_UNUSED_RESULT;
> -- 
> 2.39.2
> 

With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|
Re: [libvirt PATCH 05/28] util: move backend-agnostic virNetfilter*() functions to their own file
Posted by Laine Stump 1 year, 2 months ago
On 5/3/23 11:56 AM, Daniel P. Berrangé wrote:
> On Sun, Apr 30, 2023 at 11:19:20PM -0400, Laine Stump wrote:
>> These function are all moved into virnetfilter.[ch]. The only
>> functions from viriptables.[ch] that are still called from the
>> consumer (network bridge driver) are iptablesSetupPrivateChains()
>> (which creates the private chains that all iptables rules will be
>> added to), and iptablesAddOutputFixUdpChecksum() and
>> iptablesRemoveOutputFixUdpChecksum() (which add/remove rules to fix
>> improper checksum of DHCP packets, which is something not supported by
>> nftables)
>>
>> Signed-off-by: Laine Stump <laine@redhat.com>
>> ---
>>   src/libvirt_private.syms          |  51 +--
>>   src/network/bridge_driver_linux.c |   1 +
>>   src/util/meson.build              |   1 +
>>   src/util/viriptables.c            | 522 +--------------------------
>>   src/util/viriptables.h            | 212 +++++------
>>   src/util/virnetfilter.c           | 570 ++++++++++++++++++++++++++++++
>>   src/util/virnetfilter.h           | 151 ++++++++
>>   7 files changed, 849 insertions(+), 659 deletions(-)
>>   create mode 100644 src/util/virnetfilter.c
>>   create mode 100644 src/util/virnetfilter.h
> 
> If we move  'viriptables.{ch}' to 'src/network/bridge_iptables.{ch}
> as first step in this series, then we would naturally also
> have 'src/network/bridge_netfilter.{ch}' for this patch.

Yes! Why didn't I think of that? (rhetorical, rhetorical!)

viriptables.[ch] has always been used only by the network driver, and in 
the future it will only be used by the network driver.

Re: [libvirt PATCH 05/28] util: move backend-agnostic virNetfilter*() functions to their own file
Posted by Michal Prívozník 1 year, 2 months ago
On 5/1/23 05:19, Laine Stump wrote:
> These function are all moved into virnetfilter.[ch]. The only
> functions from viriptables.[ch] that are still called from the
> consumer (network bridge driver) are iptablesSetupPrivateChains()
> (which creates the private chains that all iptables rules will be
> added to), and iptablesAddOutputFixUdpChecksum() and
> iptablesRemoveOutputFixUdpChecksum() (which add/remove rules to fix
> improper checksum of DHCP packets, which is something not supported by
> nftables)
> 
> Signed-off-by: Laine Stump <laine@redhat.com>
> ---
>  src/libvirt_private.syms          |  51 +--
>  src/network/bridge_driver_linux.c |   1 +
>  src/util/meson.build              |   1 +
>  src/util/viriptables.c            | 522 +--------------------------
>  src/util/viriptables.h            | 212 +++++------
>  src/util/virnetfilter.c           | 570 ++++++++++++++++++++++++++++++
>  src/util/virnetfilter.h           | 151 ++++++++
>  7 files changed, 849 insertions(+), 659 deletions(-)
>  create mode 100644 src/util/virnetfilter.c
>  create mode 100644 src/util/virnetfilter.h

In cases like this I thank git developers for inventing:

  git show --color-moved

Michal