diff options
author | Lubomir Rintel <lkundrak@v3.sk> | 2015-11-30 23:07:04 +0100 |
---|---|---|
committer | Lubomir Rintel <lkundrak@v3.sk> | 2015-12-01 14:52:58 +0100 |
commit | 2fce12ca159198e87fb1a206b60d3c7dfbbe0db8 (patch) | |
tree | 483225b73210c2b9384e75042aee7bac0a331def | |
parent | ece23fa09f9c914313e12bcf94603d6849f9264f (diff) | |
download | NetworkManager-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.ac | 12 | ||||
-rw-r--r-- | src/dns-manager/nm-dns-unbound.c | 151 |
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; } |