This 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/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