This isn't yet used anywhere, since VIR_FIREWALL_TRANSACTION_AUTO_ROLLBACK isn't being set. Signed-off-by: Laine Stump <laine@xxxxxxxxxx> --- 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