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