summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLubomir Rintel <lkundrak@v3.sk>2015-11-30 23:07:04 +0100
committerLubomir Rintel <lkundrak@v3.sk>2015-12-01 14:52:58 +0100
commit2fce12ca159198e87fb1a206b60d3c7dfbbe0db8 (patch)
tree483225b73210c2b9384e75042aee7bac0a331def
parentece23fa09f9c914313e12bcf94603d6849f9264f (diff)
downloadNetworkManager-lr/dnssec.tar.gz
dns-unbound: rework the plugin for dnssec checkinglr/dnssec
XXX: Needs more work * Shouldn't we signal after a complete record (an empty line) from the results watch process? That way we could aggretgate some more information and do more granular signalling. * This SHOULD use D-Bus and not watch the process!
-rw-r--r--configure.ac12
-rw-r--r--src/dns-manager/nm-dns-unbound.c151
2 files changed, 146 insertions, 17 deletions
diff --git a/configure.ac b/configure.ac
index c028f32c54..835629bb25 100644
--- a/configure.ac
+++ b/configure.ac
@@ -797,15 +797,15 @@ fi
AC_DEFINE_UNQUOTED(DNSMASQ_PATH, "$DNSMASQ_PATH", [Define to path of dnsmasq binary])
AC_SUBST(DNSMASQ_PATH)
-# dnssec-trigger-script path
-AC_ARG_WITH(dnssec_trigger, AS_HELP_STRING([--with-dnssec-trigger=/path/to/dnssec-trigger-script], [path to unbound dnssec-trigger-script]))
+# dnssec-trigger-control path
+AC_ARG_WITH(dnssec_trigger_control, AS_HELP_STRING([--with-dnssec-trigger-control=/path/to/dnssec-trigger-control], [path to unbound dnssec-trigger-control]))
if test "x${with_dnssec_trigger}" = x; then
- AC_PATH_PROG(DNSSEC_TRIGGER_SCRIPT, dnssec-trigger-script, /usr/libexec/dnssec-trigger-script, /usr/local/libexec:/usr/local/lib:/usr/local/lib/dnssec-trigger:/usr/libexec:/usr/lib:/usr/lib/dnssec-trigger)
+ AC_PATH_PROG(DNSSEC_TRIGGER_CONTROL, dnssec-trigger-control, [], $PATH:/sbin:/usr/sbin)
else
- DNSSEC_TRIGGER_SCRIPT="$with_dnssec_trigger"
+ DNSSEC_TRIGGER_CONTROL="$with_dnssec_trigger"
fi
-AC_DEFINE_UNQUOTED(DNSSEC_TRIGGER_SCRIPT, "$DNSSEC_TRIGGER_SCRIPT", [Define to path of unbound dnssec-trigger-script])
-AC_SUBST(DNSSEC_TRIGGER_SCRIPT)
+AC_DEFINE_UNQUOTED(DNSSEC_TRIGGER_CONTROL, "$DNSSEC_TRIGGER_CONTROL", [Define to path of unbound dnssec-trigger-control])
+AC_SUBST(DNSSEC_TRIGGER_CONTROL)
# system CA certificates path
AC_ARG_WITH(system-ca-path, AS_HELP_STRING([--with-system-ca-path=/path/to/ssl/certs], [path to system CA certificates]))
diff --git a/src/dns-manager/nm-dns-unbound.c b/src/dns-manager/nm-dns-unbound.c
index 25195e909b..b8cc61c0ea 100644
--- a/src/dns-manager/nm-dns-unbound.c
+++ b/src/dns-manager/nm-dns-unbound.c
@@ -17,6 +17,7 @@
* Copyright (C) 2014 Red Hat, Inc.
* Author: Pavel Šimerda <psimerda@redhat.com>
*/
+
#include "config.h"
#include "nm-dns-unbound.h"
@@ -24,10 +25,113 @@
G_DEFINE_TYPE (NMDnsUnbound, nm_dns_unbound, NM_TYPE_DNS_PLUGIN)
+#define NM_DNS_UNBOUND_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DNS_UNBOUND, NMDnsUnboundPrivate))
+
+typedef struct {
+ GPid results_pid;
+ int results_fd;
+ guint results_id;
+ GIOChannel *results_chan;
+} NMDnsUnboundPrivate;
+
/*******************************************/
+static void
+results_cleanup (NMDnsUnbound *self)
+{
+ NMDnsUnboundPrivate *priv = NM_DNS_UNBOUND_GET_PRIVATE (self);
+
+ if (priv->results_pid == 0)
+ return;
+
+ kill (priv->results_pid, SIGTERM);
+ g_spawn_close_pid (priv->results_pid);
+ priv->results_pid = 0;
+
+ close (priv->results_fd);
+
+ g_io_channel_unref (priv->results_chan);
+ priv->results_chan = 0;
+
+ g_source_remove (priv->results_id);
+ priv->results_id = 0;
+}
+
+static void
+results_died (GPid pid, gint status, gpointer user_data)
+{
+ NMDnsUnbound *self = NM_DNS_UNBOUND (user_data);
+
+ if (status != 0) {
+ nm_log_warn (LOGD_DNS, "dns-trigger-control: PID %d died with status %d",
+ pid, status);
+ }
+
+ results_cleanup (self);
+}
+
+static gboolean
+results_in (GIOChannel *chan, GIOCondition cond, gpointer user_data)
+{
+ NMDnsPlugin *plugin = NM_DNS_PLUGIN (user_data);
+ GError *error = NULL;
+ gchar *str;
+
+ g_io_channel_read_line (chan, &str, NULL, NULL, &error);
+ if (error) {
+ nm_log_warn (LOGD_DNS, "dns-trigger-control: error reading results: '%s'",
+ error->message);
+ g_error_free (error);
+ }
+ if (str) {
+ nm_log_dbg (LOGD_DNS, "dns-trigger-control: got results '%s'", str);
+ if (g_str_has_prefix (str, "state:")) {
+ if (g_str_has_prefix (str, "state: auth secure"))
+ nm_dns_plugin_set_dnssec_level (plugin, NM_DNSSEC_AUTH_SECURE);
+ else if (g_str_has_prefix (str, "state: cache secure"))
+ nm_dns_plugin_set_dnssec_level (plugin, NM_DNSSEC_CACHE_SECURE);
+ else if (g_str_has_prefix (str, "state: disconnected secure"))
+ nm_dns_plugin_set_dnssec_level (plugin, NM_DNSSEC_DISCONNECTED_SECURE);
+ else
+ nm_dns_plugin_set_dnssec_level (plugin, NM_DNSSEC_NOT_SECURE);
+ }
+ g_free (str);
+ }
+
+ return TRUE;
+}
+
+static void
+results_watch (NMDnsUnbound *self)
+{
+ NMDnsUnboundPrivate *priv = NM_DNS_UNBOUND_GET_PRIVATE (self);
+ char *argv[3];
+ GError *error = NULL;
+
+ if (priv->results_pid)
+ return;
+
+ argv[0] = DNSSEC_TRIGGER_CONTROL;
+ argv[1] = "results";
+ argv[2] = NULL;
+
+ if (!g_spawn_async_with_pipes (NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD, NULL,
+ self, &priv->results_pid, NULL, &priv->results_fd,
+ NULL, &error)) {
+ nm_log_warn (LOGD_DNS, "dns-trigger-control: could not spawn: '%s'",
+ error->message);
+ return;
+ }
+
+ nm_log_warn (LOGD_DNS, "dns-trigger-control: running with PID %d\n", priv->results_pid);
+
+ priv->results_chan = g_io_channel_unix_new (priv->results_fd);
+ g_io_add_watch (priv->results_chan, G_IO_IN, results_in, self);
+ priv->results_id = g_child_watch_add (priv->results_pid, results_died, self);
+}
+
static gboolean
-update (NMDnsPlugin *plugin,
+update (NMDnsPlugin *self,
const GSList *vpn_configs,
const GSList *dev_configs,
const GSList *other_configs,
@@ -35,16 +139,28 @@ update (NMDnsPlugin *plugin,
const char *hostname,
char **nameservers)
{
- /* TODO: We currently call a script installed with the dnssec-trigger
- * package that queries all information itself. Later, the dependency
- * on that package will be optional and the only hard dependency will
- * be unbound.
- *
- * Unbound configuration should be later handled by this plugin directly,
- * without calling custom scripts. The dnssec-trigger functionality
- * may be eventually merged into NetworkManager.
- */
- return nm_spawn_process (DNSSEC_TRIGGER_SCRIPT " --async --update", NULL) == 0;
+ gint status;
+ gchar *ns, *cmdline;
+
+ results_watch (NM_DNS_UNBOUND (self));
+
+ ns = g_strjoinv (" ", nameservers);
+ nm_log_dbg (LOGD_DNS, "dns-trigger-control: using nameservers %s\n", ns);
+ cmdline = g_strdup_printf ("%s submit %s", DNSSEC_TRIGGER_CONTROL, ns);
+ g_free (ns);
+ status = nm_spawn_process (cmdline, NULL);
+ g_free (cmdline);
+
+ return status == 0;
+}
+
+static gboolean
+recheck (NMDnsPlugin *self)
+{
+ results_watch (NM_DNS_UNBOUND (self));
+
+ nm_log_dbg (LOGD_DNS, "dns-trigger-control: rechecking\n");
+ return nm_spawn_process (DNSSEC_TRIGGER_CONTROL " reprobe", NULL) == 0;
}
static gboolean
@@ -73,11 +189,24 @@ nm_dns_unbound_init (NMDnsUnbound *unbound)
}
static void
+dispose (GObject *object)
+{
+ results_cleanup (NM_DNS_UNBOUND (object));
+
+ G_OBJECT_CLASS (nm_dns_unbound_parent_class)->dispose (object);
+}
+
+static void
nm_dns_unbound_class_init (NMDnsUnboundClass *klass)
{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
NMDnsPluginClass *plugin_class = NM_DNS_PLUGIN_CLASS (klass);
+ object_class->dispose = dispose;
+
+ g_type_class_add_private (plugin_class, sizeof (NMDnsUnboundPrivate));
plugin_class->update = update;
+ plugin_class->recheck = recheck;
plugin_class->is_caching = is_caching;
plugin_class->get_name = get_name;
}