344 lines
9.9 KiB
Diff
344 lines
9.9 KiB
Diff
From 477f1de37ff7c911048d8d5e7f7de32f12d30b5d Mon Sep 17 00:00:00 2001
|
|
Message-Id: <477f1de37ff7c911048d8d5e7f7de32f12d30b5d@dist-git>
|
|
From: Laine Stump <laine@laine.org>
|
|
Date: Fri, 1 Feb 2019 20:29:29 -0500
|
|
Subject: [PATCH] util: new virFirewallD APIs + docs
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
virFirewallDGetBackend() reports whether firewalld is currently using
|
|
an iptables or an nftables backend.
|
|
|
|
virFirewallDGetVersion() learns the version of the firewalld running
|
|
on this system and returns it as 1000000*major + 1000*minor + micro.
|
|
|
|
virFirewallDGetZones() gets a list of all currently active firewalld
|
|
zones.
|
|
|
|
virFirewallDInterfaceSetZone() sets the firewalld zone of the given
|
|
interface.
|
|
|
|
virFirewallDZoneExists() can be used to learn whether or not a
|
|
particular zone is present and active in firewalld.
|
|
|
|
Signed-off-by: Laine Stump <laine@laine.org>
|
|
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
|
|
(cherry picked from commit 3bba4825c291e51a8cd4d497d6e919ac2ee96ff0)
|
|
|
|
Conflicts: src/util/virfirewalld.c - had to remove VIR_AUTO_PTR(), which doesn't
|
|
exist in libvirt 4.5.0, and replace with appropriately placed VIR_FREE()
|
|
|
|
https://bugzilla.redhat.com/1650320
|
|
|
|
Signed-off-by: Laine Stump <laine@laine.org>
|
|
Reviewed-by: Ján Tomko <jtomko@redhat.com>
|
|
---
|
|
src/libvirt_private.syms | 5 +
|
|
src/util/virfirewalld.c | 223 +++++++++++++++++++++++++++++++++++++++
|
|
src/util/virfirewalld.h | 15 ++-
|
|
3 files changed, 242 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
|
|
index 57948d8049..624151056a 100644
|
|
--- a/src/libvirt_private.syms
|
|
+++ b/src/libvirt_private.syms
|
|
@@ -1905,7 +1905,12 @@ virFirewallStartTransaction;
|
|
|
|
# util/virfirewalld.h
|
|
virFirewallDApplyRule;
|
|
+virFirewallDGetBackend;
|
|
+virFirewallDGetVersion;
|
|
+virFirewallDGetZones;
|
|
+virFirewallDInterfaceSetZone;
|
|
virFirewallDIsRegistered;
|
|
+virFirewallDZoneExists;
|
|
|
|
|
|
# util/virfirmware.h
|
|
diff --git a/src/util/virfirewalld.c b/src/util/virfirewalld.c
|
|
index f27ec9c124..8dd6ac2b8a 100644
|
|
--- a/src/util/virfirewalld.c
|
|
+++ b/src/util/virfirewalld.c
|
|
@@ -22,6 +22,7 @@
|
|
|
|
#include <stdarg.h>
|
|
|
|
+#include "viralloc.h"
|
|
#include "virfirewall.h"
|
|
#include "virfirewalld.h"
|
|
#define LIBVIRT_VIRFIREWALLDPRIV_H_ALLOW
|
|
@@ -46,6 +47,14 @@ VIR_ENUM_IMPL(virFirewallLayerFirewallD, VIR_FIREWALL_LAYER_LAST,
|
|
);
|
|
|
|
|
|
+VIR_ENUM_DECL(virFirewallDBackend);
|
|
+VIR_ENUM_IMPL(virFirewallDBackend, VIR_FIREWALLD_BACKEND_LAST,
|
|
+ "",
|
|
+ "iptables",
|
|
+ "nftables",
|
|
+ );
|
|
+
|
|
+
|
|
/**
|
|
* virFirewallDIsRegistered:
|
|
*
|
|
@@ -57,6 +66,197 @@ virFirewallDIsRegistered(void)
|
|
return virDBusIsServiceRegistered(VIR_FIREWALL_FIREWALLD_SERVICE);
|
|
}
|
|
|
|
+/**
|
|
+ * virFirewallDGetVersion:
|
|
+ * @version: pointer to location to save version in the form of:
|
|
+ * 1000000 * major + 1000 * minor + micro
|
|
+ *
|
|
+ * queries the firewalld version property from dbus, and converts it
|
|
+ * from a string into a number.
|
|
+ *
|
|
+ * Returns 0 if version was successfully retrieved, or -1 on error
|
|
+ */
|
|
+int
|
|
+virFirewallDGetVersion(unsigned long *version)
|
|
+{
|
|
+ int ret = -1;
|
|
+ DBusConnection *sysbus = virDBusGetSystemBus();
|
|
+ DBusMessage *reply = NULL;
|
|
+ char * versionStr = NULL;
|
|
+
|
|
+ if (!sysbus)
|
|
+ return -1;
|
|
+
|
|
+ if (virDBusCallMethod(sysbus,
|
|
+ &reply,
|
|
+ NULL,
|
|
+ VIR_FIREWALL_FIREWALLD_SERVICE,
|
|
+ "/org/fedoraproject/FirewallD1",
|
|
+ "org.freedesktop.DBus.Properties",
|
|
+ "Get",
|
|
+ "ss",
|
|
+ "org.fedoraproject.FirewallD1",
|
|
+ "version") < 0)
|
|
+ goto cleanup;
|
|
+
|
|
+ if (virDBusMessageRead(reply, "v", "s", &versionStr) < 0)
|
|
+ goto cleanup;
|
|
+
|
|
+ if (virParseVersionString(versionStr, version, false) < 0) {
|
|
+ virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
+ _("Failed to parse firewalld version '%s'"),
|
|
+ versionStr);
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ VIR_DEBUG("FirewallD version: %s - %lu", versionStr, *version);
|
|
+
|
|
+ ret = 0;
|
|
+ cleanup:
|
|
+ VIR_FREE(versionStr);
|
|
+ virDBusMessageUnref(reply);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * virFirewallDGetBackend:
|
|
+ *
|
|
+ * Returns virVirewallDBackendType value representing which packet
|
|
+ * filtering backend is currently in use by firewalld, or -1 on error.
|
|
+ */
|
|
+int
|
|
+virFirewallDGetBackend(void)
|
|
+{
|
|
+ DBusConnection *sysbus = virDBusGetSystemBus();
|
|
+ DBusMessage *reply = NULL;
|
|
+ virError error;
|
|
+ char * backendStr = NULL;
|
|
+ int backend = -1;
|
|
+
|
|
+ if (!sysbus)
|
|
+ return -1;
|
|
+
|
|
+ memset(&error, 0, sizeof(error));
|
|
+
|
|
+ if (virDBusCallMethod(sysbus,
|
|
+ &reply,
|
|
+ &error,
|
|
+ VIR_FIREWALL_FIREWALLD_SERVICE,
|
|
+ "/org/fedoraproject/FirewallD1/config",
|
|
+ "org.freedesktop.DBus.Properties",
|
|
+ "Get",
|
|
+ "ss",
|
|
+ "org.fedoraproject.FirewallD1.config",
|
|
+ "FirewallBackend") < 0)
|
|
+ goto cleanup;
|
|
+
|
|
+ if (error.level == VIR_ERR_ERROR) {
|
|
+ /* we don't want to log any error in the case that
|
|
+ * FirewallBackend isn't implemented in this firewalld, since
|
|
+ * that just means that it is an old version, and only has an
|
|
+ * iptables backend.
|
|
+ */
|
|
+ VIR_DEBUG("Failed to get FirewallBackend setting, assuming 'iptables'");
|
|
+ backend = VIR_FIREWALLD_BACKEND_IPTABLES;
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ if (virDBusMessageRead(reply, "v", "s", &backendStr) < 0)
|
|
+ goto cleanup;
|
|
+
|
|
+ VIR_DEBUG("FirewallD backend: %s", backendStr);
|
|
+
|
|
+ if ((backend = virFirewallDBackendTypeFromString(backendStr)) < 0) {
|
|
+ virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
+ _("Unrecognized firewalld backend type: %s"),
|
|
+ backendStr);
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+ cleanup:
|
|
+ VIR_FREE(backendStr);
|
|
+ virResetError(&error);
|
|
+ virDBusMessageUnref(reply);
|
|
+ return backend;
|
|
+}
|
|
+
|
|
+
|
|
+/**
|
|
+ * virFirewallDGetZones:
|
|
+ * @zones: array of char *, each entry is a null-terminated zone name
|
|
+ * @nzones: number of entries in @zones
|
|
+ *
|
|
+ * Get the number of currently active firewalld zones, and their names
|
|
+ * in an array of null-terminated strings. The memory pointed to by
|
|
+ * @zones will belong to the caller, and must be freed.
|
|
+ *
|
|
+ * Returns 0 on success, -1 (and failure logged) on error
|
|
+ */
|
|
+int
|
|
+virFirewallDGetZones(char ***zones, size_t *nzones)
|
|
+{
|
|
+ DBusConnection *sysbus = virDBusGetSystemBus();
|
|
+ DBusMessage *reply = NULL;
|
|
+ int ret = -1;
|
|
+
|
|
+ *nzones = 0;
|
|
+ *zones = NULL;
|
|
+
|
|
+ if (!sysbus)
|
|
+ return -1;
|
|
+
|
|
+ if (virDBusCallMethod(sysbus,
|
|
+ &reply,
|
|
+ NULL,
|
|
+ VIR_FIREWALL_FIREWALLD_SERVICE,
|
|
+ "/org/fedoraproject/FirewallD1",
|
|
+ "org.fedoraproject.FirewallD1.zone",
|
|
+ "getZones",
|
|
+ NULL) < 0)
|
|
+ goto cleanup;
|
|
+
|
|
+ if (virDBusMessageRead(reply, "a&s", nzones, zones) < 0)
|
|
+ goto cleanup;
|
|
+
|
|
+ ret = 0;
|
|
+ cleanup:
|
|
+ virDBusMessageUnref(reply);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+
|
|
+/**
|
|
+ * virFirewallDZoneExists:
|
|
+ * @match: name of zone to look for
|
|
+ *
|
|
+ * Returns true if the requested zone exists, or false if it doesn't exist
|
|
+ */
|
|
+bool
|
|
+virFirewallDZoneExists(const char *match)
|
|
+{
|
|
+ size_t nzones = 0, i;
|
|
+ char **zones = NULL;
|
|
+ bool result = false;
|
|
+
|
|
+ return true;
|
|
+
|
|
+ if (virFirewallDGetZones(&zones, &nzones) < 0)
|
|
+ goto cleanup;
|
|
+
|
|
+ for (i = 0; i < nzones; i++) {
|
|
+ if (STREQ_NULLABLE(zones[i], match))
|
|
+ result = true;
|
|
+ }
|
|
+
|
|
+ cleanup:
|
|
+ VIR_DEBUG("Requested zone '%s' %s exist",
|
|
+ match, result ? "does" : "doesn't");
|
|
+ for (i = 0; i < nzones; i++)
|
|
+ VIR_FREE(zones[i]);
|
|
+ VIR_FREE(zones);
|
|
+ return result;
|
|
+}
|
|
+
|
|
|
|
/**
|
|
* virFirewallDApplyRule:
|
|
@@ -149,3 +349,26 @@ virFirewallDApplyRule(virFirewallLayer layer,
|
|
virDBusMessageUnref(reply);
|
|
return ret;
|
|
}
|
|
+
|
|
+
|
|
+int
|
|
+virFirewallDInterfaceSetZone(const char *iface,
|
|
+ const char *zone)
|
|
+{
|
|
+ DBusConnection *sysbus = virDBusGetSystemBus();
|
|
+ DBusMessage *reply = NULL;
|
|
+
|
|
+ if (!sysbus)
|
|
+ return -1;
|
|
+
|
|
+ return virDBusCallMethod(sysbus,
|
|
+ &reply,
|
|
+ NULL,
|
|
+ VIR_FIREWALL_FIREWALLD_SERVICE,
|
|
+ "/org/fedoraproject/FirewallD1",
|
|
+ "org.fedoraproject.FirewallD1.zone",
|
|
+ "changeZoneOfInterface",
|
|
+ "ss",
|
|
+ zone,
|
|
+ iface);
|
|
+}
|
|
diff --git a/src/util/virfirewalld.h b/src/util/virfirewalld.h
|
|
index 83fe1149cc..f05f5f2f08 100644
|
|
--- a/src/util/virfirewalld.h
|
|
+++ b/src/util/virfirewalld.h
|
|
@@ -23,11 +23,24 @@
|
|
|
|
# define VIR_FIREWALL_FIREWALLD_SERVICE "org.fedoraproject.FirewallD1"
|
|
|
|
-int virFirewallDIsRegistered(void);
|
|
+typedef enum {
|
|
+ VIR_FIREWALLD_BACKEND_NONE,
|
|
+ VIR_FIREWALLD_BACKEND_IPTABLES,
|
|
+ VIR_FIREWALLD_BACKEND_NFTABLES,
|
|
+ VIR_FIREWALLD_BACKEND_LAST,
|
|
+} virFirewallDBackendType;
|
|
|
|
+int virFirewallDGetVersion(unsigned long *version);
|
|
+int virFirewallDGetBackend(void);
|
|
+int virFirewallDIsRegistered(void);
|
|
+int virFirewallDGetZones(char ***zones, size_t *nzones);
|
|
+bool virFirewallDZoneExists(const char *match);
|
|
int virFirewallDApplyRule(virFirewallLayer layer,
|
|
char **args, size_t argsLen,
|
|
bool ignoreErrors,
|
|
char **output);
|
|
|
|
+int virFirewallDInterfaceSetZone(const char *iface,
|
|
+ const char *zone);
|
|
+
|
|
#endif /* LIBVIRT_VIRFIREWALLD_H */
|
|
--
|
|
2.20.1
|
|
|