[libvirt] [PATCH v2 3/7] util: new virFirewallD APIs + docs

Laine Stump laine at laine.org
Fri Feb 1 01:24:54 UTC 2019


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 at laine.org>
---

Change from V1: define several new functions (previously was just a
single function, now there are 5)

 src/libvirt_private.syms |   5 +
 src/util/virfirewalld.c  | 222 +++++++++++++++++++++++++++++++++++++++
 src/util/virfirewalld.h  |  15 ++-
 3 files changed, 241 insertions(+), 1 deletion(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index d52e2412fa..bfae73878f 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1923,7 +1923,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..89cfaddd9a 100644
--- a/src/util/virfirewalld.c
+++ b/src/util/virfirewalld.c
@@ -46,6 +46,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 +65,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;
+    VIR_AUTOFREE(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:
+    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;
+    VIR_AUTOFREE(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);
+    }
+
+ cleanup:
+    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.
+ *
+ * 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++) {
+        VIR_DEBUG("FirewallD zone: %s", zones[i]);
+        if (STREQ_NULLABLE(zones[i], match))
+            result = true;
+    }
+
+ cleanup:
+    /* NB: zones points to memory inside reply, so it is cleaned
+     * up by virDBusMessageUnref, and doesn't need to be freed
+     */
+    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 +348,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




More information about the libvir-list mailing list