mirror of https://gitee.com/openkylin/libvirt.git
util: move all firewalld-specific stuff into its own files
In preparation for adding several other firewalld-specific functions, separate the code that's unique to firewalld from the more-generic "firewall" file. Signed-off-by: Laine Stump <laine@laine.org> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
parent
4bf0f390ed
commit
d8393b56e2
|
@ -131,6 +131,7 @@ typedef enum {
|
|||
VIR_FROM_PERF = 65, /* Error from perf */
|
||||
VIR_FROM_LIBSSH = 66, /* Error from libssh connection transport */
|
||||
VIR_FROM_RESCTRL = 67, /* Error from resource control */
|
||||
VIR_FROM_FIREWALLD = 68, /* Error from firewalld */
|
||||
|
||||
# ifdef VIR_ENUM_SENTINELS
|
||||
VIR_ERR_DOMAIN_LAST
|
||||
|
|
|
@ -1918,6 +1918,11 @@ virFirewallStartRollback;
|
|||
virFirewallStartTransaction;
|
||||
|
||||
|
||||
# util/virfirewalld.h
|
||||
virFirewallDApplyRule;
|
||||
virFirewallDIsRegistered;
|
||||
|
||||
|
||||
# util/virfirmware.h
|
||||
virFirmwareFreeList;
|
||||
virFirmwareParse;
|
||||
|
|
|
@ -64,6 +64,9 @@ UTIL_SOURCES = \
|
|||
util/virfirewall.c \
|
||||
util/virfirewall.h \
|
||||
util/virfirewallpriv.h \
|
||||
util/virfirewalld.c \
|
||||
util/virfirewalld.h \
|
||||
util/virfirewalldpriv.h \
|
||||
util/virfirmware.c \
|
||||
util/virfirmware.h \
|
||||
util/virgettext.c \
|
||||
|
|
|
@ -138,7 +138,8 @@ VIR_ENUM_IMPL(virErrorDomain, VIR_ERR_DOMAIN_LAST,
|
|||
"Perf", /* 65 */
|
||||
"Libssh transport layer",
|
||||
"Resource control",
|
||||
)
|
||||
"FirewallD",
|
||||
);
|
||||
|
||||
|
||||
/*
|
||||
|
|
|
@ -24,12 +24,12 @@
|
|||
|
||||
#define LIBVIRT_VIRFIREWALLPRIV_H_ALLOW
|
||||
#include "virfirewallpriv.h"
|
||||
#include "virfirewalld.h"
|
||||
#include "virerror.h"
|
||||
#include "virutil.h"
|
||||
#include "virstring.h"
|
||||
#include "vircommand.h"
|
||||
#include "virlog.h"
|
||||
#include "virdbus.h"
|
||||
#include "virfile.h"
|
||||
#include "virthread.h"
|
||||
|
||||
|
@ -46,11 +46,6 @@ VIR_ENUM_IMPL(virFirewallLayerCommand, VIR_FIREWALL_LAYER_LAST,
|
|||
IPTABLES_PATH,
|
||||
IP6TABLES_PATH);
|
||||
|
||||
VIR_ENUM_DECL(virFirewallLayerFirewallD)
|
||||
VIR_ENUM_IMPL(virFirewallLayerFirewallD, VIR_FIREWALL_LAYER_LAST,
|
||||
"eb", "ipv4", "ipv6")
|
||||
|
||||
|
||||
struct _virFirewallRule {
|
||||
virFirewallLayer layer;
|
||||
|
||||
|
@ -152,7 +147,7 @@ virFirewallValidateBackend(virFirewallBackend backend)
|
|||
VIR_DEBUG("Validating backend %d", backend);
|
||||
if (backend == VIR_FIREWALL_BACKEND_AUTOMATIC ||
|
||||
backend == VIR_FIREWALL_BACKEND_FIREWALLD) {
|
||||
int rv = virDBusIsServiceRegistered(VIR_FIREWALL_FIREWALLD_SERVICE);
|
||||
int rv = virFirewallDIsRegistered();
|
||||
|
||||
VIR_DEBUG("Firewalld is registered ? %d", rv);
|
||||
if (rv < 0) {
|
||||
|
@ -712,81 +707,8 @@ virFirewallApplyRuleFirewallD(virFirewallRulePtr rule,
|
|||
bool ignoreErrors,
|
||||
char **output)
|
||||
{
|
||||
const char *ipv = virFirewallLayerFirewallDTypeToString(rule->layer);
|
||||
DBusConnection *sysbus = virDBusGetSystemBus();
|
||||
DBusMessage *reply = NULL;
|
||||
virError error;
|
||||
int ret = -1;
|
||||
|
||||
if (!sysbus)
|
||||
return -1;
|
||||
|
||||
memset(&error, 0, sizeof(error));
|
||||
|
||||
if (!ipv) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("Unknown firewall layer %d"),
|
||||
rule->layer);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (virDBusCallMethod(sysbus,
|
||||
&reply,
|
||||
&error,
|
||||
VIR_FIREWALL_FIREWALLD_SERVICE,
|
||||
"/org/fedoraproject/FirewallD1",
|
||||
"org.fedoraproject.FirewallD1.direct",
|
||||
"passthrough",
|
||||
"sa&s",
|
||||
ipv,
|
||||
(int)rule->argsLen,
|
||||
rule->args) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (error.level == VIR_ERR_ERROR) {
|
||||
/*
|
||||
* As of firewalld-0.3.9.3-1.fc20.noarch the name and
|
||||
* message fields in the error look like
|
||||
*
|
||||
* name="org.freedesktop.DBus.Python.dbus.exceptions.DBusException"
|
||||
* message="COMMAND_FAILED: '/sbin/iptables --table filter --delete
|
||||
* INPUT --in-interface virbr0 --protocol udp --destination-port 53
|
||||
* --jump ACCEPT' failed: iptables: Bad rule (does a matching rule
|
||||
* exist in that chain?)."
|
||||
*
|
||||
* We'd like to only ignore DBus errors precisely related to the failure
|
||||
* of iptables/ebtables commands. A well designed DBus interface would
|
||||
* return specific named exceptions not the top level generic python dbus
|
||||
* exception name. With this current scheme our only option is todo a
|
||||
* sub-string match for 'COMMAND_FAILED' on the message. eg like
|
||||
*
|
||||
* if (ignoreErrors &&
|
||||
* STREQ(error.name,
|
||||
* "org.freedesktop.DBus.Python.dbus.exceptions.DBusException") &&
|
||||
* STRPREFIX(error.message, "COMMAND_FAILED"))
|
||||
* ...
|
||||
*
|
||||
* But this risks our error detecting code being broken if firewalld changes
|
||||
* ever alter the message string, so we're avoiding doing that.
|
||||
*/
|
||||
if (ignoreErrors) {
|
||||
VIR_DEBUG("Ignoring error '%s': '%s'",
|
||||
error.str1, error.message);
|
||||
} else {
|
||||
virReportErrorObject(&error);
|
||||
goto cleanup;
|
||||
}
|
||||
} else {
|
||||
if (virDBusMessageRead(reply, "s", output) < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
virResetError(&error);
|
||||
virDBusMessageUnref(reply);
|
||||
return ret;
|
||||
/* wrapper necessary because virFirewallRule is a private struct */
|
||||
return virFirewallDApplyRule(rule->layer, rule->args, rule->argsLen, ignoreErrors, output);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
* virfirewalld.c: support for firewalld (https://firewalld.org)
|
||||
*
|
||||
* Copyright (C) 2019 Red Hat, Inc.
|
||||
*
|
||||
* 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>
|
||||
|
||||
#include "virfirewall.h"
|
||||
#include "virfirewalld.h"
|
||||
#define LIBVIRT_VIRFIREWALLDPRIV_H_ALLOW
|
||||
#include "virfirewalldpriv.h"
|
||||
#include "virerror.h"
|
||||
#include "virutil.h"
|
||||
#include "virlog.h"
|
||||
#include "virdbus.h"
|
||||
|
||||
#define VIR_FROM_THIS VIR_FROM_FIREWALLD
|
||||
|
||||
VIR_LOG_INIT("util.firewalld");
|
||||
|
||||
/* used to convert virFirewallLayer enum values to strings
|
||||
* understood by the firewalld.direct "passthrough" method
|
||||
*/
|
||||
VIR_ENUM_DECL(virFirewallLayerFirewallD);
|
||||
VIR_ENUM_IMPL(virFirewallLayerFirewallD, VIR_FIREWALL_LAYER_LAST,
|
||||
"eb",
|
||||
"ipv4",
|
||||
"ipv6",
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* virFirewallDIsRegistered:
|
||||
*
|
||||
* Returns 0 if service is registered, -1 on fatal error, or -2 if service is not registered
|
||||
*/
|
||||
int
|
||||
virFirewallDIsRegistered(void)
|
||||
{
|
||||
return virDBusIsServiceRegistered(VIR_FIREWALL_FIREWALLD_SERVICE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* virFirewallDApplyRule:
|
||||
* @layer: which layer to apply the rule to
|
||||
* @args: list of args to send to this layer's passthrough command.
|
||||
* @argsLen: number of items in @args
|
||||
* @ignoreErrors: true to suppress logging of errors and return success
|
||||
* false to log errors and return actual status
|
||||
* @output: output of the direct passthrough command, if it was successful
|
||||
*/
|
||||
int
|
||||
virFirewallDApplyRule(virFirewallLayer layer,
|
||||
char **args, size_t argsLen,
|
||||
bool ignoreErrors,
|
||||
char **output)
|
||||
{
|
||||
const char *ipv = virFirewallLayerFirewallDTypeToString(layer);
|
||||
DBusConnection *sysbus = virDBusGetSystemBus();
|
||||
DBusMessage *reply = NULL;
|
||||
virError error;
|
||||
int ret = -1;
|
||||
|
||||
if (!sysbus)
|
||||
return -1;
|
||||
|
||||
memset(&error, 0, sizeof(error));
|
||||
|
||||
if (!ipv) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("Unknown firewall layer %d"),
|
||||
layer);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (virDBusCallMethod(sysbus,
|
||||
&reply,
|
||||
&error,
|
||||
VIR_FIREWALL_FIREWALLD_SERVICE,
|
||||
"/org/fedoraproject/FirewallD1",
|
||||
"org.fedoraproject.FirewallD1.direct",
|
||||
"passthrough",
|
||||
"sa&s",
|
||||
ipv,
|
||||
(int)argsLen,
|
||||
args) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (error.level == VIR_ERR_ERROR) {
|
||||
/*
|
||||
* As of firewalld-0.3.9.3-1.fc20.noarch the name and
|
||||
* message fields in the error look like
|
||||
*
|
||||
* name="org.freedesktop.DBus.Python.dbus.exceptions.DBusException"
|
||||
* message="COMMAND_FAILED: '/sbin/iptables --table filter --delete
|
||||
* INPUT --in-interface virbr0 --protocol udp --destination-port 53
|
||||
* --jump ACCEPT' failed: iptables: Bad rule (does a matching rule
|
||||
* exist in that chain?)."
|
||||
*
|
||||
* We'd like to only ignore DBus errors precisely related to the failure
|
||||
* of iptables/ebtables commands. A well designed DBus interface would
|
||||
* return specific named exceptions not the top level generic python dbus
|
||||
* exception name. With this current scheme our only option is todo a
|
||||
* sub-string match for 'COMMAND_FAILED' on the message. eg like
|
||||
*
|
||||
* if (ignoreErrors &&
|
||||
* STREQ(error.name,
|
||||
* "org.freedesktop.DBus.Python.dbus.exceptions.DBusException") &&
|
||||
* STRPREFIX(error.message, "COMMAND_FAILED"))
|
||||
* ...
|
||||
*
|
||||
* But this risks our error detecting code being broken if firewalld changes
|
||||
* ever alter the message string, so we're avoiding doing that.
|
||||
*/
|
||||
if (ignoreErrors) {
|
||||
VIR_DEBUG("Ignoring error '%s': '%s'",
|
||||
error.str1, error.message);
|
||||
} else {
|
||||
virReportErrorObject(&error);
|
||||
goto cleanup;
|
||||
}
|
||||
} else {
|
||||
if (virDBusMessageRead(reply, "s", output) < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
virResetError(&error);
|
||||
virDBusMessageUnref(reply);
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* virfirewalld.h: support for firewalld (https://firewalld.org)
|
||||
*
|
||||
* Copyright (C) 2019 Red Hat, Inc.
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef LIBVIRT_VIRFIREWALLD_H
|
||||
# define LIBVIRT_VIRFIREWALLD_H
|
||||
|
||||
# define VIR_FIREWALL_FIREWALLD_SERVICE "org.fedoraproject.FirewallD1"
|
||||
|
||||
int virFirewallDIsRegistered(void);
|
||||
|
||||
int virFirewallDApplyRule(virFirewallLayer layer,
|
||||
char **args, size_t argsLen,
|
||||
bool ignoreErrors,
|
||||
char **output);
|
||||
|
||||
#endif /* LIBVIRT_VIRFIREWALLD_H */
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* virfirewalldpriv.h: private APIs for firewalld
|
||||
*
|
||||
* Copyright (C) 2019 Red Hat, Inc.
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef LIBVIRT_VIRFIREWALLDPRIV_H_ALLOW
|
||||
# error "virfirewalldpriv.h may only be included by virfirewalld.c or test suites"
|
||||
#endif /* LIBVIRT_VIRFIREWALLDPRIV_H_ALLOW */
|
||||
|
||||
#ifndef LIBVIRT_VIRFIREWALLDPRIV_H
|
||||
# define LIBVIRT_VIRFIREWALLDPRIV_H
|
||||
|
||||
# define VIR_FIREWALL_FIREWALLD_SERVICE "org.fedoraproject.FirewallD1"
|
||||
|
||||
#endif /* LIBVIRT_VIRFIREWALLDPRIV_H */
|
|
@ -27,8 +27,6 @@
|
|||
|
||||
# include "virfirewall.h"
|
||||
|
||||
# define VIR_FIREWALL_FIREWALLD_SERVICE "org.fedoraproject.FirewallD1"
|
||||
|
||||
typedef enum {
|
||||
VIR_FIREWALL_BACKEND_AUTOMATIC,
|
||||
VIR_FIREWALL_BACKEND_DIRECT,
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
# include "vircommandpriv.h"
|
||||
# define LIBVIRT_VIRFIREWALLPRIV_H_ALLOW
|
||||
# include "virfirewallpriv.h"
|
||||
# define LIBVIRT_VIRFIREWALLDPRIV_H_ALLOW
|
||||
# include "virfirewalldpriv.h"
|
||||
# include "virmock.h"
|
||||
# define LIBVIRT_VIRDBUSPRIV_H_ALLOW
|
||||
# include "virdbuspriv.h"
|
||||
|
|
Loading…
Reference in New Issue