Signed-off-by: Jiri Denemark <jdenemar(a)redhat.com>
---
src/libvirt_private.syms | 1 +
src/util/virsystemd.c | 79 +++++++++++++++++++++++++++++++++++++++-
src/util/virsystemd.h | 5 +++
3 files changed, 84 insertions(+), 1 deletion(-)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 0be273511d..d8c566b458 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -3485,6 +3485,7 @@ virSystemdHasResolvedResetCachedValue;
virSystemdMakeScopeName;
virSystemdMakeSliceName;
virSystemdNotifyStartup;
+virSystemdResolvedRegisterNameServer;
virSystemdTerminateMachine;
diff --git a/src/util/virsystemd.c b/src/util/virsystemd.c
index 0dfc4398d0..68699929d3 100644
--- a/src/util/virsystemd.c
+++ b/src/util/virsystemd.c
@@ -34,7 +34,6 @@
#include "virerror.h"
#include "virfile.h"
#include "virhash.h"
-#include "virsocketaddr.h"
#define VIR_FROM_THIS VIR_FROM_SYSTEMD
@@ -1042,3 +1041,81 @@ virSystemdActivationFree(virSystemdActivation *act)
g_free(act);
}
+
+
+/**
+ * virSystemdResolvedRegisterNameServer:
+ * @link: network interface ID
+ * @domain: registered domain
+ * @addr: address the DNS server is listening on
+ *
+ * Talk to systemd-resolved and register a DNS server listening on @addr
+ * as a resolver for @domain. This configuration is bound to @link interface
+ * and automatically dropped when the interface goes away.
+ *
+ * Returns -2 when systemd-resolved is unavailable,
+ * -1 on error,
+ * 0 on success.
+ */
+int
+virSystemdResolvedRegisterNameServer(int link,
+ const char *domain,
+ virSocketAddr *addr)
+{
+ int rc;
+ GDBusConnection *conn;
+ GVariant *params;
+ GVariant *byteArray;
+ unsigned char addrBytes[16];
+ int nBytes;
+
+ if ((rc = virSystemdHasResolved()) < 0)
+ return rc;
+
+ if (!(conn = virGDBusGetSystemBus()))
+ return -1;
+
+ /*
+ * SetLinkDomains(in i ifindex,
+ * in a(sb) domains);
+ */
+ params = g_variant_new_parsed("(%i, [(%s, true)])",
+ (gint32) link,
+ domain);
+
+ rc = virGDBusCallMethod(conn, NULL, NULL, NULL,
+ "org.freedesktop.resolve1",
+ "/org/freedesktop/resolve1",
+ "org.freedesktop.resolve1.Manager",
+ "SetLinkDomains",
+ params);
+ g_variant_unref(params);
+
+ if (rc < 0)
+ return -1;
+
+ /*
+ * SetLinkDNS(in i ifindex,
+ * in a(iay) addresses);
+ */
+ nBytes = virSocketAddrBytes(addr, addrBytes, sizeof(addrBytes));
+ byteArray = g_variant_new_fixed_array(G_VARIANT_TYPE("y"),
+ addrBytes, nBytes, 1);
+ params = g_variant_new_parsed("(%i, [(%i, %@ay)])",
+ (gint32) link,
+ VIR_SOCKET_ADDR_FAMILY(addr),
+ byteArray);
+
+ rc = virGDBusCallMethod(conn, NULL, NULL, NULL,
+ "org.freedesktop.resolve1",
+ "/org/freedesktop/resolve1",
+ "org.freedesktop.resolve1.Manager",
+ "SetLinkDNS",
+ params);
+ g_variant_unref(params);
+
+ if (rc < 0)
+ return -1;
+
+ return 0;
+}
diff --git a/src/util/virsystemd.h b/src/util/virsystemd.h
index 65add8b5b9..b7fdaf67df 100644
--- a/src/util/virsystemd.h
+++ b/src/util/virsystemd.h
@@ -22,6 +22,7 @@
#pragma once
#include "internal.h"
+#include "virsocketaddr.h"
typedef struct _virSystemdActivation virSystemdActivation;
@@ -76,3 +77,7 @@ void virSystemdActivationClaimFDs(virSystemdActivation *act,
void virSystemdActivationFree(virSystemdActivation *act);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(virSystemdActivation, virSystemdActivationFree);
+
+int virSystemdResolvedRegisterNameServer(int link,
+ const char *domain,
+ virSocketAddr *addr);
--
2.43.0