[libvirt PATCH 20/28] util: implement rollback rule autosave for iptables backend

Laine Stump laine at redhat.com
Mon May 1 03:19:35 UTC 2023


This isn't yet used anywhere, since
VIR_FIREWALL_TRANSACTION_AUTO_ROLLBACK isn't being set.

Signed-off-by: Laine Stump <laine at redhat.com>
---
 src/util/viriptables.c | 49 +++++++++++++++++++++++++++++++++++++++---
 1 file changed, 46 insertions(+), 3 deletions(-)

diff --git a/src/util/viriptables.c b/src/util/viriptables.c
index 4e3188e4d1..b332c036cf 100644
--- a/src/util/viriptables.c
+++ b/src/util/viriptables.c
@@ -63,15 +63,21 @@ VIR_ENUM_IMPL(virIptablesAction,
               "--delete",
 );
 
+#define VIR_ARG_IS_INSERT(arg) \
+    (STREQ(arg, "--insert") || STREQ(arg, "-I") \
+     || STREQ(arg, "--append") || STREQ(arg, "-A"))
 
 int
-virIptablesApplyFirewallRule(virFirewall *firewall G_GNUC_UNUSED,
+virIptablesApplyFirewallRule(virFirewall *firewall,
                              virFirewallRule *rule,
                              char **output)
 {
     virFirewallLayer layer = virFirewallRuleGetLayer(rule);
     const char *bin = virIptablesLayerCommandTypeToString(layer);
     size_t count = virFirewallRuleGetArgCount(rule);
+    bool checkRollback = (virFirewallTransactionGetFlags(firewall)
+                          & VIR_FIREWALL_TRANSACTION_AUTO_ROLLBACK);
+    bool needRollback = false;
     g_autoptr(virCommand) cmd = NULL;
     g_autofree char *cmdStr = NULL;
     g_autofree char *error = NULL;
@@ -105,8 +111,15 @@ virIptablesApplyFirewallRule(virFirewall *firewall G_GNUC_UNUSED,
         break;
     }
 
-    for (i = 0; i < count; i++)
-        virCommandAddArg(cmd, virFirewallRuleGetArg(rule, i));
+    for (i = 0; i < count; i++) {
+        const char *arg = virFirewallRuleGetArg(rule, i);
+
+        /* the -I/-A arg could be at any position in the list */
+        if (checkRollback && VIR_ARG_IS_INSERT(arg))
+            needRollback = true;
+
+        virCommandAddArg(cmd, arg);
+    }
 
     cmdStr = virCommandToString(cmd, false);
     VIR_INFO("Applying rule '%s'", NULLSTR(cmdStr));
@@ -118,8 +131,10 @@ virIptablesApplyFirewallRule(virFirewall *firewall G_GNUC_UNUSED,
         return -1;
 
     if (status != 0) {
+        /* the command failed, decide whether or not to report it */
         if (virFirewallRuleGetIgnoreErrors(rule)) {
             VIR_DEBUG("Ignoring error running command");
+            return 0;
         } else {
             virReportError(VIR_ERR_INTERNAL_ERROR,
                            _("Failed to apply firewall rules %1$s: %2$s"),
@@ -129,6 +144,34 @@ virIptablesApplyFirewallRule(virFirewall *firewall G_GNUC_UNUSED,
         }
     }
 
+    /* the command was successful, see if we need to add a
+     * rollback rule
+     */
+
+    if (needRollback) {
+        virFirewallRule *rollback
+            = virFirewallAddRollbackRule(firewall, layer, NULL);
+        g_autofree char *rollbackStr = NULL;
+
+        for (i = 0; i < count; i++) {
+            const char *arg = virFirewallRuleGetArg(rule, i);
+
+            /* iptables --delete wants the entire commandline that
+             * was used for --insert but with s/insert/delete/
+             */
+            if (VIR_ARG_IS_INSERT(arg)) {
+                virFirewallRuleAddArg(firewall, rollback, "--delete");
+            } else {
+                virFirewallRuleAddArg(firewall, rollback, arg);
+            }
+        }
+
+        rollbackStr
+            = virFirewallRuleToString(virIptablesLayerCommandTypeToString(layer),
+                                      rollback);
+        VIR_DEBUG("Recording Rollback rule '%s'", NULLSTR(rollbackStr));
+    }
+
     return 0;
 }
 
-- 
2.39.2



More information about the libvir-list mailing list