In ebtables a subchain was created with a default accept

When converted to nftables, this resulted in an "accept" at the
end of each subchain:

chain O-v100562794-mac {
      ether daddr 52:54:00:a3:13:87 counter packets 9 bytes 1145 return
      ether daddr 33:33:00:00:00:00/16 counter packets 48 bytes 3712 return
      ether daddr ff:ff:ff:ff:ff:ff counter packets 22 bytes 924 return
      counter packets 3 bytes 384 drop
>>>>  counter packets 0 bytes 0 accept
}

In order to mimick this behavior we add an "accept" for each subchain by
calling nftablesCreateSubChainAccept after having created all of the fw rules

Signed-off-by: Dion Bosschieter <[email protected]>
---
 src/nwfilter/nwfilter_nftables_driver.c       | 60 +++++++++++++++++--
 .../stp-linux.nftables.args                   | 14 +++++
 2 files changed, 69 insertions(+), 5 deletions(-)

diff --git a/src/nwfilter/nwfilter_nftables_driver.c 
b/src/nwfilter/nwfilter_nftables_driver.c
index a72c51472f..79bd987325 100644
--- a/src/nwfilter/nwfilter_nftables_driver.c
+++ b/src/nwfilter/nwfilter_nftables_driver.c
@@ -80,9 +80,9 @@ static bool trace_enabled;
 
 #define SAME_IP_SET_NAME  "same-ip-set"
 
-#define ROOT_CHAINSETTINGS(chain, defaultPolicy) \
+#define ROOT_CHAINSETTINGS(chain) \
     "{ type filter hook "chain" priority %d;" \
-    " policy "defaultPolicy"; %s }"
+    " policy "DEFAULT_POLICY"; %s }"
 
 VIR_LOG_INIT("nwfilter.nwfilter_nftables_driver");
 
@@ -183,12 +183,12 @@ static void nftablesCreateTable(virFirewall *fw,
     fwrule = virFirewallAddCmd(fw, layer, "add", "chain", "bridge",
                                tableName, IN_CHAIN, NULL);
     virFirewallCmdAddArgFormat(fw, fwrule,
-                               ROOT_CHAINSETTINGS(IN_CHAIN, DEFAULT_POLICY),
+                               ROOT_CHAINSETTINGS(IN_CHAIN),
                                tablePriority, traceSetting);
     fwrule = virFirewallAddCmd(fw, layer, "add", "chain", "bridge",
                                tableName, OUT_CHAIN, NULL);
     virFirewallCmdAddArgFormat(fw, fwrule,
-                               ROOT_CHAINSETTINGS(OUT_CHAIN, DEFAULT_POLICY),
+                               ROOT_CHAINSETTINGS(OUT_CHAIN),
                                tablePriority, traceSetting);
 
     /* add the one jump rule based on the vmap */
@@ -1825,7 +1825,7 @@ nftablesRuleInstCommand(virFirewall *fw,
  * nftablesCreateSubChain:
  * @fw: the firewall ruleset instance
  * @layer: the firewall layer
- * @ifname : The name of the interface to apply the chain to
+ * @nftablesTableName : The name of the table to create the chain on
  * @chainPrefix: The prefix to put on the beginning of the name of the chain
  * @protoidx: Protocol id for conditional jump
  * @rootChain: The chain to define the jump on
@@ -1871,6 +1871,41 @@ nftablesCreateSubChain(virFirewall *fw,
     virFirewallCmdAddArgList(fw, fwrule, "jump", chain, NULL);
 }
 
+/*
+ * nftablesCreateSubChainAccept:
+ * @fw: the firewall ruleset instance
+ * @layer: the firewall layer
+ * @nftablesTableName : The name of the table to create the chain on
+ * @chainPrefix: The prefix to put on the beginning of the name of the chain
+ * @chainPostfix: The postfix to put at the end of the name of the chain
+ *
+ * To comply with what nwfilter ipebtables was doing for ethernet subchains
+ * we need to end with an accept on a subchain, to follow the nwfilter 
ipebtables logic
+ * on ebtables, subchains have an ACCEPT, which means, that if the end of the 
chain
+ * is reached, the packet will be accepted, not returned
+ * Ebtables chains look as follows if translated to nftables:
+ * chain O-v100562794-ipv6 {
+ *     ether type ip6 icmpv6 type 133 counter packets 0 bytes 0 drop
+ *     ether type ip6 ether type ip6 meta l4proto ipv6-icmp counter packets 54 
bytes 4368 accept
+ *     ether type ip6 ip6 daddr 2a01:7c8:fffe:3::/64 counter packets 0 bytes 0 
accept
+ *     counter packets 3 bytes 489 accept
+ * }
+ *
+ * The accept at the bottom has not been provided by the user, it got added by 
translating ebtables to nftables
+ */
+static void nftablesCreateSubChainAccept(virFirewall *fw,
+                                         virFirewallLayer layer,
+                                         const char *nftablesTableName,
+                                         const char *chainPrefix,
+                                         const char *chainPostfix)
+{
+    char chain[MAX_NF_CHAINNAME_LENGTH];
+    g_snprintf(chain, sizeof(chain), "%s-%s", chainPrefix, chainPostfix);
+
+    virFirewallAddCmd(fw, layer, "add", "rule", "bridge",
+                      nftablesTableName, chain, "accept", NULL);
+}
+
 static void
 nftablesCreateRootChainJump(virFirewall *fw,
                        virFirewallLayer layer,
@@ -2165,6 +2200,21 @@ nftablesHandleCreateChains(virFirewall *fw,
             goto cleanup;
     }
 
+    /* create subchain accepts */
+    /* to comply with what nwfilter ipebtables was doing for ethernet subchains
+     * we need to finally accept on a subchain, to follow the nwfilter 
ipebtables logic
+     * on ebtables, subchains have an ACCEPT, which means, that if the end of 
the chain
+     * is reached, the packet will be accepted, not returned
+     */
+     for (i = 0; i < nchains; i++) {
+        if (chains[i]->ethernetInChain)
+            nftablesCreateSubChainAccept(fw, layer, NF_ETHERNET_TABLE,
+                                         chains[i]->prefix, "in");
+        if (chains[i]->ethernetOutChain)
+            nftablesCreateSubChainAccept(fw, layer, NF_ETHERNET_TABLE,
+                                         chains[i]->prefix, "out");
+    }
+
     /* creation of temp jumps is done as libvirt doesn't execute
      * atomic nft changes (yet) */
     nftablesCreateRootChainJump(fw, layer, cbdata->ifname, IN_IFMATCH,
diff --git a/tests/nwfilterxml2firewalldata/stp-linux.nftables.args 
b/tests/nwfilterxml2firewalldata/stp-linux.nftables.args
index 4dabd3cbc2..85ee588a16 100644
--- a/tests/nwfilterxml2firewalldata/stp-linux.nftables.args
+++ b/tests/nwfilterxml2firewalldata/stp-linux.nftables.args
@@ -111,6 +111,20 @@ nft \
 add \
 rule \
 bridge \
+libvirt_nwfilter_ethernet \
+n-vnet0-stp-xyz-in \
+accept
+nft \
+add \
+rule \
+bridge \
+libvirt_nwfilter_ethernet \
+n-vnet0-stp-xyz-out \
+accept
+nft \
+add \
+rule \
+bridge \
 libvirt_nwfilter_inet \
 postrouting \
 oif \
-- 
2.53.0

Reply via email to