On a Sunday in 2023, Laine Stump wrote:
Determining the correct rollback rule for nftables is more
complicated
than iptables - nftables give each new table/chain/rule a handle, and
the nft delete command to delete the object must contain that handle
(rather than just replicating the entire original commandline as is
done for iptables).
The handle is obtained by adding an extra "-ae" option to the original
nft commandline, and then parsing stdout of the command looking for "#
handle n" (where "n" is a decimal integer).
This code isn't yet used anywhere, since
VIR_FIREWALL_TRANSACTION_AUTO_ROLLBACK isn't being set.
Signed-off-by: Laine Stump <laine(a)redhat.com>
---
src/util/virnftables.c | 106 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 105 insertions(+), 1 deletion(-)
diff --git a/src/util/virnftables.c b/src/util/virnftables.c
index b43b14bb82..0cc09caaed 100644
--- a/src/util/virnftables.c
+++ b/src/util/virnftables.c
@@ -71,12 +71,18 @@ VIR_ENUM_IMPL(virNftablesAction,
);
+#define VIR_ARG_IS_INSERT(arg) \
+ (STREQ(arg, "insert") || STREQ(arg, "add") || STREQ(arg,
"create"))
+
int
virNftablesApplyFirewallRule(virFirewall *firewall G_GNUC_UNUSED,
virFirewallRule *rule,
char **output)
{
size_t count = virFirewallRuleGetArgCount(rule);
+ bool needRollback = false;
+ size_t cmdIdx = 0;
+ const char *objectType = NULL;
g_autoptr(virCommand) cmd = NULL;
g_autofree char *cmdStr = NULL;
g_autofree char *error = NULL;
@@ -91,11 +97,45 @@ virNftablesApplyFirewallRule(virFirewall *firewall G_GNUC_UNUSED,
cmd = virCommandNew(NFT);
+ if ((virFirewallTransactionGetFlags(firewall)
+ & VIR_FIREWALL_TRANSACTION_AUTO_ROLLBACK)
+ && count > 1) {
+ /* skip any leading options to get to command verb */
+ for (i = 0; i < count - 1; i++) {
+ if (virFirewallRuleGetArg(rule, i)[0] != '-')
+ break;
+ }
+
+ if (i + 1 < count
+ && VIR_ARG_IS_INSERT(virFirewallRuleGetArg(rule, i))) {
+
+ cmdIdx = i;
+ objectType = virFirewallRuleGetArg(rule, i + 1);
+
+ /* we currently only handle auto-rollback for rules,
+ * chains, and tables, and those all can be "rolled
+ * back" by a delete command using the handle that is
+ * returned when "-ae" is added to the add/insert
+ * command.
+ */
+ if (STREQ_NULLABLE(objectType, "rule")
+ || STREQ_NULLABLE(objectType, "chain")
+ || STREQ_NULLABLE(objectType, "table")) {
+
Same nitpick about operands on the next line applies here.
Jano