virFirewallNewFromRollback() creates a new virFirewall object that
contains a copy of the "rollback" rules from an existing virFirewall
object, but in reverse order. The intent is that this virFirewall be
saved and used later to remove the firewall rules that were added for
a network.
Signed-off-by: Laine Stump <laine(a)redhat.com>
---
src/libvirt_private.syms | 1 +
src/util/virfirewall.c | 59 ++++++++++++++++++++++++++++++++++++++++
src/util/virfirewall.h | 1 +
3 files changed, 61 insertions(+)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index df84c5520c..7eeed1efd4 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2379,6 +2379,7 @@ virFirewallBackendTypeToString;
virFirewallFree;
virFirewallGetBackend;
virFirewallNew;
+virFirewallNewFromRollback;
virFirewallRemoveRule;
virFirewallRuleAddArg;
virFirewallRuleAddArgFormat;
diff --git a/src/util/virfirewall.c b/src/util/virfirewall.c
index c59166b843..f598cc9d79 100644
--- a/src/util/virfirewall.c
+++ b/src/util/virfirewall.c
@@ -680,3 +680,62 @@ virFirewallApply(virFirewall *firewall)
return 0;
}
+
+
+/**
+ * virFirewallNewFromRollback:
+
+ * @original: the original virFirewall object containing the rollback
+ * of interest
+ * @fwRemoval: a firewall object that, when applied, will remove @original
+ *
+ * Copy the rollback rules from the current virFirewall object as a
+ * new virFirewall. This virFirewall can then be saved to apply later
+ * and counteract everything done by the original.
+ *
+ * Returns 0 on success, -1 on error
+ */
+int
+virFirewallNewFromRollback(virFirewall *original,
+ virFirewall **fwRemoval)
+{
+ size_t g;
+ g_autoptr(virFirewall) firewall = NULL;
+
+ if (original->err) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("error in original firewall object"));
+ return -1;
+ }
+
+ firewall = virFirewallNew(original->backend);
+
+ /* add the rollback commands in reverse order of actions/groups of
+ * what was applied in the original firewall.
+ */
+ for (g = original->ngroups; g > 0; g--) {
+ size_t r;
+ virFirewallGroup *group = original->groups[g - 1];
+
+ if (group->nrollback == 0)
+ continue;
+
+ virFirewallStartTransaction(firewall, VIR_FIREWALL_TRANSACTION_IGNORE_ERRORS);
+
+ for (r = group->nrollback; r > 0; r--) {
+ size_t i;
+ virFirewallRule *origRule = group->rollback[r - 1];
+ virFirewallRule *rule = virFirewallAddRule(firewall, origRule->layer,
NULL);
+
+ for (i = 0; i < origRule->argsLen; i++)
+ ADD_ARG(rule, origRule->args[i]);
+ }
+ }
+
+ if (firewall->ngroups == 0)
+ VIR_DEBUG("original firewall object is empty");
+ else
+ *fwRemoval = g_steal_pointer(&firewall);
+
+ return 0;
+}
diff --git a/src/util/virfirewall.h b/src/util/virfirewall.h
index f81b63567a..9017c12b5c 100644
--- a/src/util/virfirewall.h
+++ b/src/util/virfirewall.h
@@ -54,6 +54,7 @@ typedef enum {
VIR_ENUM_DECL(virFirewallBackend);
virFirewall *virFirewallNew(virFirewallBackend backend);
+int virFirewallNewFromRollback(virFirewall *original, virFirewall **fwRemoval);
void virFirewallFree(virFirewall *firewall);
virFirewallBackend virFirewallGetBackend(virFirewall *firewall);
--
2.39.2