2013-03-04 16:30:40 +00:00
|
|
|
/*
|
|
|
|
* virfirewall.c: integration with firewalls
|
|
|
|
*
|
2015-05-21 13:36:18 -04:00
|
|
|
* Copyright (C) 2013-2015 Red Hat, Inc.
|
2013-03-04 16:30:40 +00:00
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library. If not, see
|
|
|
|
* <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
2021-11-16 14:27:00 -05:00
|
|
|
#include "virfirewall.h"
|
2019-01-09 14:11:32 -05:00
|
|
|
#include "virfirewalld.h"
|
2019-04-01 16:28:05 +02:00
|
|
|
#include "viralloc.h"
|
2013-03-04 16:30:40 +00:00
|
|
|
#include "virerror.h"
|
|
|
|
#include "vircommand.h"
|
|
|
|
#include "virlog.h"
|
|
|
|
#include "virfile.h"
|
|
|
|
#include "virthread.h"
|
|
|
|
|
|
|
|
#define VIR_FROM_THIS VIR_FROM_FIREWALL
|
|
|
|
|
|
|
|
VIR_LOG_INIT("util.firewall");
|
|
|
|
|
util/network: new virFirewallBackend enum
(This paragraph is for historical reference only, described only to
avoid confusion of past use of the name with its new use) In a past
life, virFirewallBackend had been a private static in virfirewall.c
that was set at daemon init time, and used to globally (i.e. for all
drivers in the daemon) determine whether to directly execute iptables
commands, or to run them indirectly via the firewalld passthrough
API. This was removed in commit d566cc55, since we decided that using
the firewalld passthrough API is never appropriate.
Now the same enum, virFirewallBackend, is being reintroduced, with a
different meaning and usage pattern. It will be used to pick between
using nftables commands or iptables commands (in either case directly
handled by libvirt, *not* via firewalld). Additionally, rather than
being a static known only within virfirewall.c and applying to all
firewall commands for all drivers, each virFirewall object will have
its own backend setting, which will be set during virFirewallNew() by
the driver who wants to add a firewall rule.
This will allow the nwfilter and network drivers to each have their
own backend setting, even when they coexist in a single unified
daemon. At least as important as that, it will also allow an instance
of the network driver to remove iptables rules that had been added by
a previous instance, and then add nftables rules for the new instance
(in the case that an admin, or possibly an update, switches the driver
backend from iptables to nftable)
Initially, the enum will only have one usable value -
VIR_FIREWALL_BACKEND_IPTABLES, and that will be hardcoded into all
calls to virFirewallNew(). The other enum value (along with a method
of setting it for each driver) will be added later, when it can be
used (when the nftables backend is in the code).
Signed-off-by: Laine Stump <laine@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
2024-04-19 22:19:42 -04:00
|
|
|
VIR_ENUM_IMPL(virFirewallBackend,
|
|
|
|
VIR_FIREWALL_BACKEND_LAST,
|
|
|
|
"iptables");
|
|
|
|
|
2013-03-04 16:30:40 +00:00
|
|
|
typedef struct _virFirewallGroup virFirewallGroup;
|
|
|
|
|
2019-01-20 11:04:56 -05:00
|
|
|
VIR_ENUM_DECL(virFirewallLayerCommand);
|
2019-03-16 14:20:32 -04:00
|
|
|
VIR_ENUM_IMPL(virFirewallLayerCommand,
|
|
|
|
VIR_FIREWALL_LAYER_LAST,
|
2021-09-14 10:40:42 +02:00
|
|
|
EBTABLES,
|
|
|
|
IPTABLES,
|
|
|
|
IP6TABLES,
|
2019-01-20 11:30:15 -05:00
|
|
|
);
|
2013-03-04 16:30:40 +00:00
|
|
|
|
2024-04-19 22:19:42 -04:00
|
|
|
struct _virFirewallCmd {
|
2013-03-04 16:30:40 +00:00
|
|
|
virFirewallLayer layer;
|
|
|
|
|
|
|
|
virFirewallQueryCallback queryCB;
|
|
|
|
void *queryOpaque;
|
|
|
|
bool ignoreErrors;
|
|
|
|
|
|
|
|
size_t argsAlloc;
|
|
|
|
size_t argsLen;
|
|
|
|
char **args;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct _virFirewallGroup {
|
|
|
|
unsigned int actionFlags;
|
|
|
|
unsigned int rollbackFlags;
|
|
|
|
|
|
|
|
size_t naction;
|
2024-04-19 22:19:42 -04:00
|
|
|
virFirewallCmd **action;
|
2013-03-04 16:30:40 +00:00
|
|
|
|
|
|
|
size_t nrollback;
|
2024-04-19 22:19:42 -04:00
|
|
|
virFirewallCmd **rollback;
|
2013-03-04 16:30:40 +00:00
|
|
|
|
|
|
|
bool addingRollback;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct _virFirewall {
|
|
|
|
int err;
|
|
|
|
|
|
|
|
size_t ngroups;
|
2021-03-11 08:16:13 +01:00
|
|
|
virFirewallGroup **groups;
|
2013-03-04 16:30:40 +00:00
|
|
|
size_t currentGroup;
|
util/network: new virFirewallBackend enum
(This paragraph is for historical reference only, described only to
avoid confusion of past use of the name with its new use) In a past
life, virFirewallBackend had been a private static in virfirewall.c
that was set at daemon init time, and used to globally (i.e. for all
drivers in the daemon) determine whether to directly execute iptables
commands, or to run them indirectly via the firewalld passthrough
API. This was removed in commit d566cc55, since we decided that using
the firewalld passthrough API is never appropriate.
Now the same enum, virFirewallBackend, is being reintroduced, with a
different meaning and usage pattern. It will be used to pick between
using nftables commands or iptables commands (in either case directly
handled by libvirt, *not* via firewalld). Additionally, rather than
being a static known only within virfirewall.c and applying to all
firewall commands for all drivers, each virFirewall object will have
its own backend setting, which will be set during virFirewallNew() by
the driver who wants to add a firewall rule.
This will allow the nwfilter and network drivers to each have their
own backend setting, even when they coexist in a single unified
daemon. At least as important as that, it will also allow an instance
of the network driver to remove iptables rules that had been added by
a previous instance, and then add nftables rules for the new instance
(in the case that an admin, or possibly an update, switches the driver
backend from iptables to nftable)
Initially, the enum will only have one usable value -
VIR_FIREWALL_BACKEND_IPTABLES, and that will be hardcoded into all
calls to virFirewallNew(). The other enum value (along with a method
of setting it for each driver) will be added later, when it can be
used (when the nftables backend is in the code).
Signed-off-by: Laine Stump <laine@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
2024-04-19 22:19:42 -04:00
|
|
|
virFirewallBackend backend;
|
2013-03-04 16:30:40 +00:00
|
|
|
};
|
|
|
|
|
2024-04-19 22:19:42 -04:00
|
|
|
static virMutex fwCmdLock = VIR_MUTEX_INITIALIZER;
|
2013-03-04 16:30:40 +00:00
|
|
|
|
2021-03-11 08:16:13 +01:00
|
|
|
static virFirewallGroup *
|
2013-03-04 16:30:40 +00:00
|
|
|
virFirewallGroupNew(void)
|
|
|
|
{
|
2021-10-22 10:56:01 +02:00
|
|
|
return g_new0(virFirewallGroup, 1);
|
2013-03-04 16:30:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virFirewallNew:
|
|
|
|
*
|
|
|
|
* Creates a new firewall ruleset for changing rules
|
|
|
|
* of @layer. This should be followed by a call to
|
|
|
|
* virFirewallStartTransaction before adding
|
|
|
|
* any rules
|
|
|
|
*
|
|
|
|
* Returns the new firewall ruleset
|
|
|
|
*/
|
util/network: new virFirewallBackend enum
(This paragraph is for historical reference only, described only to
avoid confusion of past use of the name with its new use) In a past
life, virFirewallBackend had been a private static in virfirewall.c
that was set at daemon init time, and used to globally (i.e. for all
drivers in the daemon) determine whether to directly execute iptables
commands, or to run them indirectly via the firewalld passthrough
API. This was removed in commit d566cc55, since we decided that using
the firewalld passthrough API is never appropriate.
Now the same enum, virFirewallBackend, is being reintroduced, with a
different meaning and usage pattern. It will be used to pick between
using nftables commands or iptables commands (in either case directly
handled by libvirt, *not* via firewalld). Additionally, rather than
being a static known only within virfirewall.c and applying to all
firewall commands for all drivers, each virFirewall object will have
its own backend setting, which will be set during virFirewallNew() by
the driver who wants to add a firewall rule.
This will allow the nwfilter and network drivers to each have their
own backend setting, even when they coexist in a single unified
daemon. At least as important as that, it will also allow an instance
of the network driver to remove iptables rules that had been added by
a previous instance, and then add nftables rules for the new instance
(in the case that an admin, or possibly an update, switches the driver
backend from iptables to nftable)
Initially, the enum will only have one usable value -
VIR_FIREWALL_BACKEND_IPTABLES, and that will be hardcoded into all
calls to virFirewallNew(). The other enum value (along with a method
of setting it for each driver) will be added later, when it can be
used (when the nftables backend is in the code).
Signed-off-by: Laine Stump <laine@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
2024-04-19 22:19:42 -04:00
|
|
|
virFirewall *virFirewallNew(virFirewallBackend backend)
|
2013-03-04 16:30:40 +00:00
|
|
|
{
|
2021-11-17 13:20:53 -05:00
|
|
|
virFirewall *firewall = g_new0(virFirewall, 1);
|
2013-03-04 16:30:40 +00:00
|
|
|
|
util/network: new virFirewallBackend enum
(This paragraph is for historical reference only, described only to
avoid confusion of past use of the name with its new use) In a past
life, virFirewallBackend had been a private static in virfirewall.c
that was set at daemon init time, and used to globally (i.e. for all
drivers in the daemon) determine whether to directly execute iptables
commands, or to run them indirectly via the firewalld passthrough
API. This was removed in commit d566cc55, since we decided that using
the firewalld passthrough API is never appropriate.
Now the same enum, virFirewallBackend, is being reintroduced, with a
different meaning and usage pattern. It will be used to pick between
using nftables commands or iptables commands (in either case directly
handled by libvirt, *not* via firewalld). Additionally, rather than
being a static known only within virfirewall.c and applying to all
firewall commands for all drivers, each virFirewall object will have
its own backend setting, which will be set during virFirewallNew() by
the driver who wants to add a firewall rule.
This will allow the nwfilter and network drivers to each have their
own backend setting, even when they coexist in a single unified
daemon. At least as important as that, it will also allow an instance
of the network driver to remove iptables rules that had been added by
a previous instance, and then add nftables rules for the new instance
(in the case that an admin, or possibly an update, switches the driver
backend from iptables to nftable)
Initially, the enum will only have one usable value -
VIR_FIREWALL_BACKEND_IPTABLES, and that will be hardcoded into all
calls to virFirewallNew(). The other enum value (along with a method
of setting it for each driver) will be added later, when it can be
used (when the nftables backend is in the code).
Signed-off-by: Laine Stump <laine@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
2024-04-19 22:19:42 -04:00
|
|
|
firewall->backend = backend;
|
2013-03-04 16:30:40 +00:00
|
|
|
return firewall;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
util/network: new virFirewallBackend enum
(This paragraph is for historical reference only, described only to
avoid confusion of past use of the name with its new use) In a past
life, virFirewallBackend had been a private static in virfirewall.c
that was set at daemon init time, and used to globally (i.e. for all
drivers in the daemon) determine whether to directly execute iptables
commands, or to run them indirectly via the firewalld passthrough
API. This was removed in commit d566cc55, since we decided that using
the firewalld passthrough API is never appropriate.
Now the same enum, virFirewallBackend, is being reintroduced, with a
different meaning and usage pattern. It will be used to pick between
using nftables commands or iptables commands (in either case directly
handled by libvirt, *not* via firewalld). Additionally, rather than
being a static known only within virfirewall.c and applying to all
firewall commands for all drivers, each virFirewall object will have
its own backend setting, which will be set during virFirewallNew() by
the driver who wants to add a firewall rule.
This will allow the nwfilter and network drivers to each have their
own backend setting, even when they coexist in a single unified
daemon. At least as important as that, it will also allow an instance
of the network driver to remove iptables rules that had been added by
a previous instance, and then add nftables rules for the new instance
(in the case that an admin, or possibly an update, switches the driver
backend from iptables to nftable)
Initially, the enum will only have one usable value -
VIR_FIREWALL_BACKEND_IPTABLES, and that will be hardcoded into all
calls to virFirewallNew(). The other enum value (along with a method
of setting it for each driver) will be added later, when it can be
used (when the nftables backend is in the code).
Signed-off-by: Laine Stump <laine@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
2024-04-19 22:19:42 -04:00
|
|
|
virFirewallBackend
|
|
|
|
virFirewallGetBackend(virFirewall *firewall)
|
|
|
|
{
|
|
|
|
return firewall->backend;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-03-04 16:30:40 +00:00
|
|
|
static void
|
2024-04-19 22:19:42 -04:00
|
|
|
virFirewallCmdFree(virFirewallCmd *fwCmd)
|
2013-03-04 16:30:40 +00:00
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
2024-04-19 22:19:42 -04:00
|
|
|
if (!fwCmd)
|
2013-03-04 16:30:40 +00:00
|
|
|
return;
|
|
|
|
|
2024-04-19 22:19:42 -04:00
|
|
|
for (i = 0; i < fwCmd->argsLen; i++)
|
|
|
|
g_free(fwCmd->args[i]);
|
|
|
|
g_free(fwCmd->args);
|
|
|
|
g_free(fwCmd);
|
2013-03-04 16:30:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2021-03-11 08:16:13 +01:00
|
|
|
virFirewallGroupFree(virFirewallGroup *group)
|
2013-03-04 16:30:40 +00:00
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
if (!group)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (i = 0; i < group->naction; i++)
|
2024-04-19 22:19:42 -04:00
|
|
|
virFirewallCmdFree(group->action[i]);
|
2021-02-03 14:32:34 -05:00
|
|
|
g_free(group->action);
|
2013-03-04 16:30:40 +00:00
|
|
|
|
|
|
|
for (i = 0; i < group->nrollback; i++)
|
2024-04-19 22:19:42 -04:00
|
|
|
virFirewallCmdFree(group->rollback[i]);
|
2021-02-03 14:32:34 -05:00
|
|
|
g_free(group->rollback);
|
2013-03-04 16:30:40 +00:00
|
|
|
|
2021-02-03 14:32:34 -05:00
|
|
|
g_free(group);
|
2013-03-04 16:30:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virFirewallFree:
|
|
|
|
*
|
|
|
|
* Release all memory associated with the firewall
|
|
|
|
* ruleset
|
|
|
|
*/
|
2021-03-11 08:16:13 +01:00
|
|
|
void virFirewallFree(virFirewall *firewall)
|
2013-03-04 16:30:40 +00:00
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
if (!firewall)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (i = 0; i < firewall->ngroups; i++)
|
|
|
|
virFirewallGroupFree(firewall->groups[i]);
|
2021-02-03 14:32:34 -05:00
|
|
|
g_free(firewall->groups);
|
2013-03-04 16:30:40 +00:00
|
|
|
|
2021-02-03 14:32:34 -05:00
|
|
|
g_free(firewall);
|
2013-03-04 16:30:40 +00:00
|
|
|
}
|
|
|
|
|
2017-11-03 13:09:47 +01:00
|
|
|
#define VIR_FIREWALL_RETURN_IF_ERROR(firewall) \
|
|
|
|
do { \
|
|
|
|
if (!firewall || firewall->err) \
|
|
|
|
return; \
|
2013-03-04 16:30:40 +00:00
|
|
|
} while (0)
|
|
|
|
|
2024-04-19 22:19:42 -04:00
|
|
|
#define VIR_FIREWALL_CMD_RETURN_IF_ERROR(firewall, fwCmd)\
|
2017-11-03 13:09:47 +01:00
|
|
|
do { \
|
2024-04-19 22:19:42 -04:00
|
|
|
if (!firewall || firewall->err || !fwCmd) \
|
2017-11-03 13:09:47 +01:00
|
|
|
return; \
|
2013-03-04 16:30:40 +00:00
|
|
|
} while (0)
|
|
|
|
|
2017-11-03 13:09:47 +01:00
|
|
|
#define VIR_FIREWALL_RETURN_NULL_IF_ERROR(firewall) \
|
|
|
|
do { \
|
|
|
|
if (!firewall || firewall->err) \
|
|
|
|
return NULL; \
|
2013-03-04 16:30:40 +00:00
|
|
|
} while (0)
|
|
|
|
|
2024-04-19 22:19:42 -04:00
|
|
|
#define ADD_ARG(fwCmd, str) \
|
2017-11-03 13:09:47 +01:00
|
|
|
do { \
|
2024-04-19 22:19:42 -04:00
|
|
|
VIR_RESIZE_N(fwCmd->args, fwCmd->argsAlloc, fwCmd->argsLen, 1); \
|
|
|
|
fwCmd->args[fwCmd->argsLen++] = g_strdup(str); \
|
2013-03-04 16:30:40 +00:00
|
|
|
} while (0)
|
|
|
|
|
2024-04-19 22:19:42 -04:00
|
|
|
|
2024-04-19 22:19:42 -04:00
|
|
|
static virFirewallCmd *
|
|
|
|
virFirewallAddCmdFullV(virFirewall *firewall,
|
|
|
|
virFirewallLayer layer,
|
|
|
|
bool ignoreErrors,
|
2024-04-19 22:19:42 -04:00
|
|
|
bool isRollback,
|
2024-04-19 22:19:42 -04:00
|
|
|
virFirewallQueryCallback cb,
|
|
|
|
void *opaque,
|
|
|
|
va_list args)
|
2013-03-04 16:30:40 +00:00
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
virFirewallGroup *group;
|
2024-04-19 22:19:42 -04:00
|
|
|
virFirewallCmd *fwCmd;
|
2013-03-04 16:30:40 +00:00
|
|
|
char *str;
|
|
|
|
|
|
|
|
VIR_FIREWALL_RETURN_NULL_IF_ERROR(firewall);
|
|
|
|
|
|
|
|
if (firewall->ngroups == 0) {
|
2014-04-30 08:51:29 +02:00
|
|
|
firewall->err = EINVAL;
|
2013-03-04 16:30:40 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
group = firewall->groups[firewall->currentGroup];
|
|
|
|
|
2024-04-19 22:19:42 -04:00
|
|
|
fwCmd = g_new0(virFirewallCmd, 1);
|
|
|
|
fwCmd->layer = layer;
|
2013-03-04 16:30:40 +00:00
|
|
|
|
2014-11-13 15:28:18 +01:00
|
|
|
while ((str = va_arg(args, char *)) != NULL)
|
2024-04-19 22:19:42 -04:00
|
|
|
ADD_ARG(fwCmd, str);
|
2013-03-04 16:30:40 +00:00
|
|
|
|
2024-04-19 22:19:42 -04:00
|
|
|
if (isRollback || group->addingRollback) {
|
2024-04-19 22:19:42 -04:00
|
|
|
fwCmd->ignoreErrors = true; /* always ignore errors when rolling back */
|
2024-04-19 22:19:42 -04:00
|
|
|
fwCmd->queryCB = NULL; /* rollback commands can't have a callback */
|
|
|
|
fwCmd->queryOpaque = NULL;
|
2024-04-19 22:19:42 -04:00
|
|
|
VIR_APPEND_ELEMENT_COPY(group->rollback, group->nrollback, fwCmd);
|
2013-03-04 16:30:40 +00:00
|
|
|
} else {
|
2024-04-19 22:19:42 -04:00
|
|
|
/* when not rolling back, ignore errors if this group (transaction)
|
|
|
|
* was started with VIR_FIREWALL_TRANSACTION_IGNORE_ERRORS *or*
|
|
|
|
* if this specific rule was created with ignoreErrors == true
|
|
|
|
*/
|
|
|
|
fwCmd->ignoreErrors = ignoreErrors || (group->actionFlags & VIR_FIREWALL_TRANSACTION_IGNORE_ERRORS);
|
2024-04-19 22:19:42 -04:00
|
|
|
fwCmd->queryCB = cb;
|
|
|
|
fwCmd->queryOpaque = opaque;
|
2024-04-19 22:19:42 -04:00
|
|
|
VIR_APPEND_ELEMENT_COPY(group->action, group->naction, fwCmd);
|
2013-03-04 16:30:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-04-19 22:19:42 -04:00
|
|
|
return fwCmd;
|
2013-03-04 16:30:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2024-04-19 22:19:42 -04:00
|
|
|
* virFirewallAddCmdFull:
|
2013-03-04 16:30:40 +00:00
|
|
|
* @firewall: firewall ruleset to add to
|
|
|
|
* @layer: the firewall layer to change
|
|
|
|
* @ignoreErrors: true to ignore failure of the command
|
|
|
|
* @cb: callback to invoke with result of query
|
|
|
|
* @opaque: data passed into @cb
|
|
|
|
* @...: NULL terminated list of strings for the rule
|
|
|
|
*
|
|
|
|
* Add any type of rule to the firewall ruleset. Any output
|
|
|
|
* generated by the addition will be fed into the query
|
|
|
|
* callback @cb. This callback is permitted to create new
|
2024-04-19 22:19:42 -04:00
|
|
|
* rules by invoking the virFirewallAddCmd method, but
|
2013-03-04 16:30:40 +00:00
|
|
|
* is not permitted to start new transactions.
|
|
|
|
*
|
|
|
|
* If @ignoreErrors is set to TRUE, then any failure of
|
|
|
|
* the command is ignored. If it is set to FALSE, then
|
|
|
|
* the behaviour upon failure is determined by the flags
|
|
|
|
* set when the transaction was started.
|
|
|
|
*
|
|
|
|
* Returns the new rule
|
|
|
|
*/
|
2024-04-19 22:19:42 -04:00
|
|
|
virFirewallCmd *virFirewallAddCmdFull(virFirewall *firewall,
|
|
|
|
virFirewallLayer layer,
|
|
|
|
bool ignoreErrors,
|
|
|
|
virFirewallQueryCallback cb,
|
|
|
|
void *opaque,
|
|
|
|
...)
|
2013-03-04 16:30:40 +00:00
|
|
|
{
|
2024-04-19 22:19:42 -04:00
|
|
|
virFirewallCmd *fwCmd;
|
2013-03-04 16:30:40 +00:00
|
|
|
va_list args;
|
|
|
|
va_start(args, opaque);
|
2024-04-19 22:19:42 -04:00
|
|
|
fwCmd = virFirewallAddCmdFullV(firewall, layer, ignoreErrors, false, cb, opaque, args);
|
|
|
|
va_end(args);
|
|
|
|
return fwCmd;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virFirewallAddRollbackCmd:
|
|
|
|
* @firewall: firewall commands to add to
|
|
|
|
* @layer: the firewall layer to change
|
|
|
|
* @...: NULL terminated list of strings for the command
|
|
|
|
*
|
|
|
|
* Add a command to the current firewall command group "rollback".
|
|
|
|
* Rollback commands always ignore errors and don't support any
|
|
|
|
* callbacks.
|
|
|
|
*
|
|
|
|
* Returns the new Command
|
|
|
|
*/
|
|
|
|
virFirewallCmd *
|
|
|
|
virFirewallAddRollbackCmd(virFirewall *firewall,
|
|
|
|
virFirewallLayer layer,
|
|
|
|
...)
|
|
|
|
{
|
|
|
|
virFirewallCmd *fwCmd;
|
|
|
|
va_list args;
|
|
|
|
va_start(args, layer);
|
|
|
|
fwCmd = virFirewallAddCmdFullV(firewall, layer, true, true, NULL, NULL, args);
|
2013-03-04 16:30:40 +00:00
|
|
|
va_end(args);
|
2024-04-19 22:19:42 -04:00
|
|
|
return fwCmd;
|
2013-03-04 16:30:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2024-04-19 22:19:42 -04:00
|
|
|
* virFirewallRemoveCmd:
|
2013-03-04 16:30:40 +00:00
|
|
|
* @firewall: firewall ruleset to remove from
|
|
|
|
* @rule: the rule to remove
|
|
|
|
*
|
|
|
|
* Remove a rule from the current transaction
|
|
|
|
*/
|
2024-04-19 22:19:42 -04:00
|
|
|
void virFirewallRemoveCmd(virFirewall *firewall,
|
|
|
|
virFirewallCmd *fwCmd)
|
2013-03-04 16:30:40 +00:00
|
|
|
{
|
|
|
|
size_t i;
|
2021-03-11 08:16:13 +01:00
|
|
|
virFirewallGroup *group;
|
2013-03-04 16:30:40 +00:00
|
|
|
|
|
|
|
/* Explicitly not checking firewall->err too,
|
|
|
|
* because if rule was partially created
|
|
|
|
* before hitting error we must still remove
|
|
|
|
* it to avoid leaking 'rule'
|
|
|
|
*/
|
|
|
|
if (!firewall)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (firewall->ngroups == 0)
|
|
|
|
return;
|
|
|
|
group = firewall->groups[firewall->currentGroup];
|
|
|
|
|
|
|
|
if (group->addingRollback) {
|
|
|
|
for (i = 0; i < group->nrollback; i++) {
|
2024-04-19 22:19:42 -04:00
|
|
|
if (group->rollback[i] == fwCmd) {
|
2013-03-04 16:30:40 +00:00
|
|
|
VIR_DELETE_ELEMENT(group->rollback,
|
|
|
|
i,
|
|
|
|
group->nrollback);
|
2024-04-19 22:19:42 -04:00
|
|
|
virFirewallCmdFree(fwCmd);
|
2013-03-04 16:30:40 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (i = 0; i < group->naction; i++) {
|
2024-04-19 22:19:42 -04:00
|
|
|
if (group->action[i] == fwCmd) {
|
2013-03-04 16:30:40 +00:00
|
|
|
VIR_DELETE_ELEMENT(group->action,
|
|
|
|
i,
|
|
|
|
group->naction);
|
2024-04-19 22:19:42 -04:00
|
|
|
virFirewallCmdFree(fwCmd);
|
2013-03-04 16:30:40 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-04-19 22:19:42 -04:00
|
|
|
void virFirewallCmdAddArg(virFirewall *firewall,
|
|
|
|
virFirewallCmd *fwCmd,
|
|
|
|
const char *arg)
|
2013-03-04 16:30:40 +00:00
|
|
|
{
|
2024-04-19 22:19:42 -04:00
|
|
|
VIR_FIREWALL_CMD_RETURN_IF_ERROR(firewall, fwCmd);
|
2013-03-04 16:30:40 +00:00
|
|
|
|
2024-04-19 22:19:42 -04:00
|
|
|
ADD_ARG(fwCmd, arg);
|
2013-03-04 16:30:40 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-04-19 22:19:42 -04:00
|
|
|
void virFirewallCmdAddArgFormat(virFirewall *firewall,
|
|
|
|
virFirewallCmd *fwCmd,
|
|
|
|
const char *fmt, ...)
|
2013-03-04 16:30:40 +00:00
|
|
|
{
|
2019-10-15 15:16:31 +02:00
|
|
|
g_autofree char *arg = NULL;
|
2013-03-04 16:30:40 +00:00
|
|
|
va_list list;
|
|
|
|
|
2024-04-19 22:19:42 -04:00
|
|
|
VIR_FIREWALL_CMD_RETURN_IF_ERROR(firewall, fwCmd);
|
2013-03-04 16:30:40 +00:00
|
|
|
|
|
|
|
va_start(list, fmt);
|
2019-10-22 14:11:15 +02:00
|
|
|
arg = g_strdup_vprintf(fmt, list);
|
|
|
|
va_end(list);
|
2013-03-04 16:30:40 +00:00
|
|
|
|
2024-04-19 22:19:42 -04:00
|
|
|
ADD_ARG(fwCmd, arg);
|
2013-03-04 16:30:40 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-04-19 22:19:42 -04:00
|
|
|
void virFirewallCmdAddArgSet(virFirewall *firewall,
|
|
|
|
virFirewallCmd *fwCmd,
|
|
|
|
const char *const *args)
|
2013-03-04 16:30:40 +00:00
|
|
|
{
|
2024-04-19 22:19:42 -04:00
|
|
|
VIR_FIREWALL_CMD_RETURN_IF_ERROR(firewall, fwCmd);
|
2013-03-04 16:30:40 +00:00
|
|
|
|
|
|
|
while (*args) {
|
2024-04-19 22:19:42 -04:00
|
|
|
ADD_ARG(fwCmd, *args);
|
2013-03-04 16:30:40 +00:00
|
|
|
args++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-04-19 22:19:42 -04:00
|
|
|
void virFirewallCmdAddArgList(virFirewall *firewall,
|
|
|
|
virFirewallCmd *fwCmd,
|
|
|
|
...)
|
2013-03-04 16:30:40 +00:00
|
|
|
{
|
|
|
|
va_list list;
|
|
|
|
const char *str;
|
|
|
|
|
2024-04-19 22:19:42 -04:00
|
|
|
VIR_FIREWALL_CMD_RETURN_IF_ERROR(firewall, fwCmd);
|
2013-03-04 16:30:40 +00:00
|
|
|
|
2024-04-19 22:19:42 -04:00
|
|
|
va_start(list, fwCmd);
|
2013-03-04 16:30:40 +00:00
|
|
|
|
2014-11-13 15:28:18 +01:00
|
|
|
while ((str = va_arg(list, char *)) != NULL)
|
2024-04-19 22:19:42 -04:00
|
|
|
ADD_ARG(fwCmd, str);
|
2013-03-04 16:30:40 +00:00
|
|
|
|
|
|
|
va_end(list);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-04-19 22:19:42 -04:00
|
|
|
size_t virFirewallCmdGetArgCount(virFirewallCmd *fwCmd)
|
2013-03-04 16:30:40 +00:00
|
|
|
{
|
2024-04-19 22:19:42 -04:00
|
|
|
if (!fwCmd)
|
2013-03-04 16:30:40 +00:00
|
|
|
return 0;
|
2024-04-19 22:19:42 -04:00
|
|
|
return fwCmd->argsLen;
|
2013-03-04 16:30:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virFirewallStartTransaction:
|
|
|
|
* @firewall: the firewall ruleset
|
|
|
|
* @flags: bitset of virFirewallTransactionFlags
|
|
|
|
*
|
|
|
|
* Start a new transaction with associated rollback
|
|
|
|
* block.
|
|
|
|
*
|
|
|
|
* Should be followed by calls to add various rules to
|
|
|
|
* the transaction. Then virFirwallStartRollback should
|
|
|
|
* be used to provide rules to rollback upon transaction
|
|
|
|
* failure
|
|
|
|
*/
|
2021-03-11 08:16:13 +01:00
|
|
|
void virFirewallStartTransaction(virFirewall *firewall,
|
2013-03-04 16:30:40 +00:00
|
|
|
unsigned int flags)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
virFirewallGroup *group;
|
2013-03-04 16:30:40 +00:00
|
|
|
|
|
|
|
VIR_FIREWALL_RETURN_IF_ERROR(firewall);
|
|
|
|
|
2021-02-23 17:36:36 +01:00
|
|
|
group = virFirewallGroupNew();
|
2013-03-04 16:30:40 +00:00
|
|
|
group->actionFlags = flags;
|
|
|
|
|
2021-03-20 00:37:03 +01:00
|
|
|
VIR_EXPAND_N(firewall->groups, firewall->ngroups, 1);
|
2013-03-04 16:30:40 +00:00
|
|
|
firewall->groups[firewall->ngroups - 1] = group;
|
|
|
|
firewall->currentGroup = firewall->ngroups - 1;
|
|
|
|
}
|
|
|
|
|
2024-04-19 22:19:42 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* virFirewallTransactionGetFlags:
|
|
|
|
* @firewall: the firewall to look at
|
|
|
|
*
|
|
|
|
* Returns the virFirewallTransactionFlags for the currently active
|
|
|
|
* group (transaction) in @firewall.
|
|
|
|
*/
|
2024-04-19 22:19:42 -04:00
|
|
|
static virFirewallTransactionFlags
|
2024-04-19 22:19:42 -04:00
|
|
|
virFirewallTransactionGetFlags(virFirewall *firewall)
|
|
|
|
{
|
|
|
|
return firewall->groups[firewall->currentGroup]->actionFlags;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-03-04 16:30:40 +00:00
|
|
|
/**
|
|
|
|
* virFirewallBeginRollback:
|
|
|
|
* @firewall: the firewall ruleset
|
|
|
|
* @flags: bitset of virFirewallRollbackFlags
|
|
|
|
*
|
|
|
|
* Mark the beginning of a set of rules able to rollback
|
|
|
|
* changes in this and all earlier transactions.
|
|
|
|
*
|
|
|
|
* Should be followed by calls to add various rules needed
|
|
|
|
* to rollback state. Then virFirewallStartTransaction
|
|
|
|
* should be used to indicate the beginning of the next
|
|
|
|
* transactional ruleset.
|
|
|
|
*/
|
2021-03-11 08:16:13 +01:00
|
|
|
void virFirewallStartRollback(virFirewall *firewall,
|
2013-03-04 16:30:40 +00:00
|
|
|
unsigned int flags)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
virFirewallGroup *group;
|
2013-03-04 16:30:40 +00:00
|
|
|
|
|
|
|
VIR_FIREWALL_RETURN_IF_ERROR(firewall);
|
|
|
|
|
|
|
|
if (firewall->ngroups == 0) {
|
2014-04-30 08:51:29 +02:00
|
|
|
firewall->err = EINVAL;
|
2013-03-04 16:30:40 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
group = firewall->groups[firewall->ngroups-1];
|
|
|
|
group->rollbackFlags = flags;
|
|
|
|
group->addingRollback = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-04-21 17:42:30 -04:00
|
|
|
char *
|
2024-04-19 22:19:42 -04:00
|
|
|
virFirewallCmdToString(const char *cmd,
|
|
|
|
virFirewallCmd *fwCmd)
|
2013-03-04 16:30:40 +00:00
|
|
|
{
|
2020-07-02 22:30:20 -04:00
|
|
|
g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
|
2013-03-04 16:30:40 +00:00
|
|
|
size_t i;
|
|
|
|
|
2022-04-21 17:42:30 -04:00
|
|
|
virBufferAdd(&buf, cmd, -1);
|
2024-04-19 22:19:42 -04:00
|
|
|
for (i = 0; i < fwCmd->argsLen; i++) {
|
2013-03-04 16:30:40 +00:00
|
|
|
virBufferAddLit(&buf, " ");
|
2024-04-19 22:19:42 -04:00
|
|
|
virBufferAdd(&buf, fwCmd->args[i], -1);
|
2013-03-04 16:30:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return virBufferContentAndReset(&buf);
|
|
|
|
}
|
|
|
|
|
2022-04-21 17:42:30 -04:00
|
|
|
|
2024-04-19 22:19:42 -04:00
|
|
|
#define VIR_IPTABLES_ARG_IS_CREATE(arg) \
|
|
|
|
(STREQ(arg, "--insert") || STREQ(arg, "-I") || \
|
|
|
|
STREQ(arg, "--append") || STREQ(arg, "-A"))
|
|
|
|
|
|
|
|
|
2013-03-04 16:30:40 +00:00
|
|
|
static int
|
2024-04-19 22:19:42 -04:00
|
|
|
virFirewallCmdIptablesApply(virFirewall *firewall,
|
|
|
|
virFirewallCmd *fwCmd,
|
|
|
|
char **output)
|
2013-03-04 16:30:40 +00:00
|
|
|
{
|
2024-04-19 22:19:42 -04:00
|
|
|
const char *bin = virFirewallLayerCommandTypeToString(fwCmd->layer);
|
2024-04-19 22:19:42 -04:00
|
|
|
bool checkRollback = (virFirewallTransactionGetFlags(firewall) &
|
|
|
|
VIR_FIREWALL_TRANSACTION_AUTO_ROLLBACK);
|
|
|
|
bool needRollback = false;
|
2019-10-15 14:47:50 +02:00
|
|
|
g_autoptr(virCommand) cmd = NULL;
|
2022-03-13 14:21:02 -04:00
|
|
|
g_autofree char *cmdStr = NULL;
|
2019-10-15 15:16:31 +02:00
|
|
|
g_autofree char *error = NULL;
|
2024-04-19 22:19:42 -04:00
|
|
|
size_t i;
|
|
|
|
int status;
|
2013-03-04 16:30:40 +00:00
|
|
|
|
|
|
|
if (!bin) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
2023-03-09 15:13:35 +01:00
|
|
|
_("Unknown firewall layer %1$d"),
|
2024-04-19 22:19:42 -04:00
|
|
|
fwCmd->layer);
|
2018-07-24 21:22:17 +05:30
|
|
|
return -1;
|
2013-03-04 16:30:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
cmd = virCommandNewArgList(bin, NULL);
|
|
|
|
|
2024-04-19 22:19:42 -04:00
|
|
|
/* lock to assure nobody else is messing with the tables while we are */
|
|
|
|
switch (fwCmd->layer) {
|
|
|
|
case VIR_FIREWALL_LAYER_ETHERNET:
|
|
|
|
virCommandAddArg(cmd, "--concurrent");
|
|
|
|
break;
|
|
|
|
case VIR_FIREWALL_LAYER_IPV4:
|
|
|
|
case VIR_FIREWALL_LAYER_IPV6:
|
|
|
|
virCommandAddArg(cmd, "-w");
|
|
|
|
break;
|
|
|
|
case VIR_FIREWALL_LAYER_LAST:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2024-04-19 22:19:42 -04:00
|
|
|
for (i = 0; i < fwCmd->argsLen; i++) {
|
|
|
|
/* the -I/-A arg could be at any position in the list */
|
|
|
|
if (checkRollback && VIR_IPTABLES_ARG_IS_CREATE(fwCmd->args[i]))
|
|
|
|
needRollback = true;
|
|
|
|
|
2024-04-19 22:19:42 -04:00
|
|
|
virCommandAddArg(cmd, fwCmd->args[i]);
|
2024-04-19 22:19:42 -04:00
|
|
|
}
|
2013-03-04 16:30:40 +00:00
|
|
|
|
2022-03-13 14:21:02 -04:00
|
|
|
cmdStr = virCommandToString(cmd, false);
|
2024-04-19 22:19:42 -04:00
|
|
|
VIR_INFO("Running firewall command '%s'", NULLSTR(cmdStr));
|
2022-03-13 14:21:02 -04:00
|
|
|
|
2013-03-04 16:30:40 +00:00
|
|
|
virCommandSetOutputBuffer(cmd, output);
|
|
|
|
virCommandSetErrorBuffer(cmd, &error);
|
|
|
|
|
|
|
|
if (virCommandRun(cmd, &status) < 0)
|
2018-07-24 21:22:17 +05:30
|
|
|
return -1;
|
2013-03-04 16:30:40 +00:00
|
|
|
|
|
|
|
if (status != 0) {
|
2024-04-19 22:19:42 -04:00
|
|
|
/* the command failed, decide whether or not to report it */
|
2024-04-19 22:19:42 -04:00
|
|
|
if (fwCmd->ignoreErrors) {
|
2013-03-04 16:30:40 +00:00
|
|
|
VIR_DEBUG("Ignoring error running command");
|
2024-04-19 22:19:42 -04:00
|
|
|
return 0;
|
2013-03-04 16:30:40 +00:00
|
|
|
} else {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
2024-04-19 22:19:42 -04:00
|
|
|
_("Failed to run firewall command %1$s: %2$s"),
|
2022-03-13 14:21:02 -04:00
|
|
|
NULLSTR(cmdStr), NULLSTR(error));
|
2013-03-04 16:30:40 +00:00
|
|
|
VIR_FREE(*output);
|
2018-07-24 21:22:17 +05:30
|
|
|
return -1;
|
2013-03-04 16:30:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-19 22:19:42 -04:00
|
|
|
/* the command was successful, see if we need to add a
|
|
|
|
* rollback command
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (needRollback) {
|
|
|
|
virFirewallCmd *rollback
|
|
|
|
= virFirewallAddRollbackCmd(firewall, fwCmd->layer, NULL);
|
|
|
|
g_autofree char *rollbackStr = NULL;
|
|
|
|
|
|
|
|
for (i = 0; i < fwCmd->argsLen; i++) {
|
|
|
|
/* iptables --delete wants the entire commandline that
|
|
|
|
* was used for --insert but with s/insert/delete/
|
|
|
|
*/
|
|
|
|
if (VIR_IPTABLES_ARG_IS_CREATE(fwCmd->args[i])) {
|
|
|
|
virFirewallCmdAddArg(firewall, rollback, "--delete");
|
|
|
|
} else {
|
|
|
|
virFirewallCmdAddArg(firewall, rollback, fwCmd->args[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
rollbackStr = virFirewallCmdToString(virFirewallLayerCommandTypeToString(fwCmd->layer),
|
|
|
|
rollback);
|
|
|
|
VIR_DEBUG("Recording Rollback command '%s'", NULLSTR(rollbackStr));
|
|
|
|
}
|
|
|
|
|
2018-07-24 21:22:17 +05:30
|
|
|
return 0;
|
2013-03-04 16:30:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2024-04-19 22:19:42 -04:00
|
|
|
virFirewallApplyCmd(virFirewall *firewall,
|
2024-04-19 22:19:42 -04:00
|
|
|
virFirewallCmd *fwCmd)
|
2013-03-04 16:30:40 +00:00
|
|
|
{
|
2019-10-15 15:16:31 +02:00
|
|
|
g_autofree char *output = NULL;
|
2020-12-01 09:21:32 +01:00
|
|
|
g_auto(GStrv) lines = NULL;
|
2013-03-04 16:30:40 +00:00
|
|
|
|
2024-04-19 22:19:42 -04:00
|
|
|
if (fwCmd->argsLen == 0) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Can't apply empty firewall command"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2024-04-19 22:19:42 -04:00
|
|
|
if (virFirewallCmdIptablesApply(firewall, fwCmd, &output) < 0)
|
2013-03-04 16:30:40 +00:00
|
|
|
return -1;
|
|
|
|
|
2024-04-19 22:19:42 -04:00
|
|
|
if (fwCmd->queryCB && output) {
|
2021-02-05 18:35:07 +01:00
|
|
|
if (!(lines = g_strsplit(output, "\n", -1)))
|
2018-07-24 21:22:17 +05:30
|
|
|
return -1;
|
2013-03-04 16:30:40 +00:00
|
|
|
|
2024-04-19 22:19:42 -04:00
|
|
|
VIR_DEBUG("Invoking query %p with '%s'", fwCmd->queryCB, output);
|
|
|
|
if (fwCmd->queryCB(firewall, fwCmd->layer, (const char *const *)lines, fwCmd->queryOpaque) < 0)
|
2018-07-24 21:22:17 +05:30
|
|
|
return -1;
|
2013-03-04 16:30:40 +00:00
|
|
|
|
|
|
|
if (firewall->err) {
|
|
|
|
virReportSystemError(firewall->err, "%s",
|
2024-04-19 22:19:42 -04:00
|
|
|
_("Unable to create firewall command"));
|
2018-07-24 21:22:17 +05:30
|
|
|
return -1;
|
2013-03-04 16:30:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-07-24 21:22:17 +05:30
|
|
|
return 0;
|
2013-03-04 16:30:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2021-03-11 08:16:13 +01:00
|
|
|
virFirewallApplyGroup(virFirewall *firewall,
|
2013-03-04 16:30:40 +00:00
|
|
|
size_t idx)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
virFirewallGroup *group = firewall->groups[idx];
|
2024-04-19 22:19:42 -04:00
|
|
|
|
2013-03-04 16:30:40 +00:00
|
|
|
size_t i;
|
|
|
|
|
2017-09-25 11:43:33 +01:00
|
|
|
VIR_INFO("Starting transaction for firewall=%p group=%p flags=0x%x",
|
2014-11-11 12:34:57 +00:00
|
|
|
firewall, group, group->actionFlags);
|
2013-03-04 16:30:40 +00:00
|
|
|
firewall->currentGroup = idx;
|
|
|
|
group->addingRollback = false;
|
|
|
|
for (i = 0; i < group->naction; i++) {
|
2024-04-19 22:19:42 -04:00
|
|
|
if (virFirewallApplyCmd(firewall, group->action[i]) < 0)
|
2013-03-04 16:30:40 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2021-03-11 08:16:13 +01:00
|
|
|
virFirewallRollbackGroup(virFirewall *firewall,
|
2013-03-04 16:30:40 +00:00
|
|
|
size_t idx)
|
|
|
|
{
|
2021-03-11 08:16:13 +01:00
|
|
|
virFirewallGroup *group = firewall->groups[idx];
|
2013-03-04 16:30:40 +00:00
|
|
|
size_t i;
|
|
|
|
|
|
|
|
VIR_INFO("Starting rollback for group %p", group);
|
|
|
|
firewall->currentGroup = idx;
|
|
|
|
group->addingRollback = true;
|
2024-04-19 22:19:42 -04:00
|
|
|
for (i = 0; i < group->nrollback; i++)
|
2024-04-19 22:19:42 -04:00
|
|
|
ignore_value(virFirewallApplyCmd(firewall, group->rollback[i]));
|
2013-03-04 16:30:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2021-03-11 08:16:13 +01:00
|
|
|
virFirewallApply(virFirewall *firewall)
|
2013-03-04 16:30:40 +00:00
|
|
|
{
|
|
|
|
size_t i, j;
|
2024-04-19 22:19:42 -04:00
|
|
|
VIR_LOCK_GUARD lock = virLockGuardLock(&fwCmdLock);
|
2013-03-04 16:30:40 +00:00
|
|
|
|
2021-02-23 17:39:50 +01:00
|
|
|
if (!firewall || firewall->err) {
|
2021-03-05 10:38:49 +01:00
|
|
|
int err = EINVAL;
|
|
|
|
|
|
|
|
if (firewall)
|
|
|
|
err = firewall->err;
|
|
|
|
|
2024-04-19 22:19:42 -04:00
|
|
|
virReportSystemError(err, "%s", _("Unable to create firewall command"));
|
2022-02-08 14:59:30 +01:00
|
|
|
return -1;
|
2013-03-04 16:30:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
VIR_DEBUG("Applying groups for %p", firewall);
|
|
|
|
for (i = 0; i < firewall->ngroups; i++) {
|
|
|
|
if (virFirewallApplyGroup(firewall, i) < 0) {
|
|
|
|
size_t first = i;
|
2018-12-06 12:33:39 -05:00
|
|
|
virErrorPtr saved_error;
|
|
|
|
|
2020-08-03 17:28:06 +02:00
|
|
|
VIR_DEBUG("Rolling back groups up to %zu for %p", i, firewall);
|
|
|
|
|
2018-12-06 12:33:39 -05:00
|
|
|
virErrorPreserveLast(&saved_error);
|
2013-03-04 16:30:40 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Look at any inheritance markers to figure out
|
|
|
|
* what the first rollback group we need to apply is
|
|
|
|
*/
|
|
|
|
for (j = 0; j < i; j++) {
|
|
|
|
VIR_DEBUG("Checking inheritance of group %zu", i - j);
|
|
|
|
if (firewall->groups[i - j]->rollbackFlags &
|
|
|
|
VIR_FIREWALL_ROLLBACK_INHERIT_PREVIOUS)
|
|
|
|
first = (i - j) - 1;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Now apply all rollback groups in order
|
|
|
|
*/
|
|
|
|
for (j = first; j <= i; j++) {
|
|
|
|
VIR_DEBUG("Rolling back group %zu", j);
|
|
|
|
virFirewallRollbackGroup(firewall, j);
|
|
|
|
}
|
|
|
|
|
2018-12-06 12:33:39 -05:00
|
|
|
virErrorRestore(&saved_error);
|
2013-03-04 16:30:40 +00:00
|
|
|
VIR_DEBUG("Done rolling back groups for %p", firewall);
|
2022-02-08 14:59:30 +01:00
|
|
|
return -1;
|
2013-03-04 16:30:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
VIR_DEBUG("Done applying groups for %p", firewall);
|
|
|
|
|
2022-02-08 14:59:30 +01:00
|
|
|
return 0;
|
2013-03-04 16:30:40 +00:00
|
|
|
}
|