VIR_ONCE_GLOBAL_INIT(virFirewall)
+static bool iptablesUseLock;
+static bool ip6tablesUseLock;
+static bool ebtablesUseLock;
+
+static void
+virFirewallCheckUpdateLock(bool *lockflag,
+ const char *const*args)
+{
+ virCommandPtr cmd = virCommandNewArgs(args);
+ if (virCommandRun(cmd, NULL) < 0) {
+ VIR_INFO("locking not supported by %s", args[0]);
+ } else {
+ VIR_INFO("using locking for %s", args[0]);
+ *lockflag = true;
+ }
+ virCommandFree(cmd);
+}
+
+static void
+virFirewallCheckUpdateLocking(void)
+{
+ const char *iptablesArgs[] = {
+ IPTABLES_PATH, "-w", "-L", "-n", NULL,
+ };
+ const char *ip6tablesArgs[] = {
+ IP6TABLES_PATH, "-w", "-L", "-n", NULL,
+ };
+ const char *ebtablesArgs[] = {
+ EBTABLES_PATH, "--concurrent", "-L", NULL,
+ };
+ virFirewallCheckUpdateLock(&iptablesUseLock,
+ iptablesArgs);
+ virFirewallCheckUpdateLock(&ip6tablesUseLock,
+ ip6tablesArgs);
+ virFirewallCheckUpdateLock(&ebtablesUseLock,
+ ebtablesArgs);
+}
+
static int
virFirewallValidateBackend(virFirewallBackend backend)
{
}
currentBackend = backend;
+
+ virFirewallCheckUpdateLocking();
+
return 0;
}
{
virFirewallPtr firewall;
+ if (virFirewallInitialize() < 0)
+ return NULL;
+
if (VIR_ALLOC(firewall) < 0)
return NULL;
rule->queryOpaque = opaque;
rule->ignoreErrors = ignoreErrors;
+ switch (rule->layer) {
+ case VIR_FIREWALL_LAYER_ETHERNET:
+ if (ebtablesUseLock)
+ ADD_ARG(rule, "--concurrent");
+ break;
+ case VIR_FIREWALL_LAYER_IPV4:
+ if (iptablesUseLock)
+ ADD_ARG(rule, "-w");
+ break;
+ case VIR_FIREWALL_LAYER_IPV6:
+ if (ip6tablesUseLock)
+ ADD_ARG(rule, "-w");
+ break;
+ case VIR_FIREWALL_LAYER_LAST:
+ break;
+ }
+
while ((str = va_arg(args, char *)) != NULL) {
ADD_ARG(rule, str);
}
bool ignoreErrors = (group->actionFlags & VIR_FIREWALL_TRANSACTION_IGNORE_ERRORS);
size_t i;
- VIR_INFO("Starting transaction for %p flags=%x",
- group, group->actionFlags);
+ VIR_INFO("Starting transaction for firewall=%p group=%p flags=%x",
+ firewall, group, group->actionFlags);
firewall->currentGroup = idx;
group->addingRollback = false;
for (i = 0; i < group->naction; i++) {
int ret = -1;
virMutexLock(&ruleLock);
- if (virFirewallInitialize() < 0)
- goto cleanup;
if (!firewall || firewall->err == ENOMEM) {
virReportOOMError();