dns: first cut of a dnsmasq local caching plugin
This commit is contained in:
@@ -6,13 +6,18 @@ INCLUDES = \
|
|||||||
|
|
||||||
noinst_LTLIBRARIES = libdns-manager.la
|
noinst_LTLIBRARIES = libdns-manager.la
|
||||||
|
|
||||||
libdns_manager_la_SOURCES = nm-dns-manager.h nm-dns-manager.c
|
libdns_manager_la_SOURCES = \
|
||||||
|
nm-dns-manager.h \
|
||||||
|
nm-dns-manager.c \
|
||||||
|
nm-dns-plugin.h \
|
||||||
|
nm-dns-plugin.c \
|
||||||
|
nm-dns-dnsmasq.h \
|
||||||
|
nm-dns-dnsmasq.c
|
||||||
|
|
||||||
libdns_manager_la_CPPFLAGS = \
|
libdns_manager_la_CPPFLAGS = \
|
||||||
$(DBUS_CFLAGS) \
|
$(DBUS_CFLAGS) \
|
||||||
$(GLIB_CFLAGS) \
|
$(GLIB_CFLAGS) \
|
||||||
-DNM_PKGDATADIR=\"$(pkgdatadir)\" \
|
-DLOCALSTATEDIR=\"$(localstatedir)\"
|
||||||
-DNM_LOCALSTATEDIR=\"$(localstatedir)\"
|
|
||||||
|
|
||||||
libdns_manager_la_LIBADD = \
|
libdns_manager_la_LIBADD = \
|
||||||
$(top_builddir)/src/logging/libnm-logging.la \
|
$(top_builddir)/src/logging/libnm-logging.la \
|
||||||
|
391
src/dns-manager/nm-dns-dnsmasq.c
Normal file
391
src/dns-manager/nm-dns-dnsmasq.c
Normal file
@@ -0,0 +1,391 @@
|
|||||||
|
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2010 Dan Williams <dcbw@redhat.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
|
||||||
|
#include "nm-dns-dnsmasq.h"
|
||||||
|
#include "nm-logging.h"
|
||||||
|
#include "nm-ip4-config.h"
|
||||||
|
#include "nm-ip6-config.h"
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (NMDnsDnsmasq, nm_dns_dnsmasq, NM_TYPE_DNS_PLUGIN)
|
||||||
|
|
||||||
|
#define NM_DNS_DNSMASQ_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DNS_DNSMASQ, NMDnsDnsmasqPrivate))
|
||||||
|
|
||||||
|
#define PIDFILE LOCALSTATEDIR "/run/nm-dns-dnsmasq.pid"
|
||||||
|
#define CONFFILE LOCALSTATEDIR "/run/nm-dns-dnsmasq.conf"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int pid;
|
||||||
|
} NMDnsDnsmasqPrivate;
|
||||||
|
|
||||||
|
/*******************************************/
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static NMCmdLine *
|
||||||
|
create_dm_cmd_line (const char *iface,
|
||||||
|
const char *pidfile,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
const char *dm_binary;
|
||||||
|
GString *conf;
|
||||||
|
NMIP4Address *tmp;
|
||||||
|
struct in_addr addr;
|
||||||
|
char buf[INET_ADDRSTRLEN + 15];
|
||||||
|
char localaddr[INET_ADDRSTRLEN + 1];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
dm_binary = nm_find_dnsmasq ();
|
||||||
|
if (!dm_binary) {
|
||||||
|
nm_log_warn (LOGD_DNS, "could not find dnsmasq binary.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create dnsmasq command line */
|
||||||
|
cmd = nm_cmd_line_new ();
|
||||||
|
nm_cmd_line_add_string (cmd, dm_binary);
|
||||||
|
|
||||||
|
if (getenv ("NM_DNSMASQ_DEBUG"))
|
||||||
|
nm_cmd_line_add_string (cmd, "--log-queries");
|
||||||
|
|
||||||
|
/* dnsmasq may read from it's default config file location, which if that
|
||||||
|
* location is a valid config file, it will combine with the options here
|
||||||
|
* and cause undesirable side-effects. Like sending bogus IP addresses
|
||||||
|
* as the gateway or whatever. So give dnsmasq a bogus config file
|
||||||
|
* location to avoid screwing up the configuration we're passing to it.
|
||||||
|
*/
|
||||||
|
memset (buf, 0, sizeof (buf));
|
||||||
|
strcpy (buf, "/tmp/");
|
||||||
|
for (i = 5; i < 15; i++)
|
||||||
|
buf[i] = (char) (g_random_int_range ((guint32) 'a', (guint32) 'z') & 0xFF);
|
||||||
|
strcat (buf, ".conf");
|
||||||
|
|
||||||
|
nm_cmd_line_add_string (cmd, "--conf-file");
|
||||||
|
nm_cmd_line_add_string (cmd, buf);
|
||||||
|
|
||||||
|
nm_cmd_line_add_string (cmd, "--no-hosts");
|
||||||
|
nm_cmd_line_add_string (cmd, "--keep-in-foreground");
|
||||||
|
nm_cmd_line_add_string (cmd, "--bind-interfaces");
|
||||||
|
nm_cmd_line_add_string (cmd, "--except-interface=lo");
|
||||||
|
nm_cmd_line_add_string (cmd, "--clear-on-reload");
|
||||||
|
|
||||||
|
/* Use strict order since in the case of VPN connections, the VPN's
|
||||||
|
* nameservers will be first in resolv.conf, and those need to be tried
|
||||||
|
* first by dnsmasq to successfully resolve names from the VPN.
|
||||||
|
*/
|
||||||
|
nm_cmd_line_add_string (cmd, "--strict-order");
|
||||||
|
|
||||||
|
s = g_string_new ("--listen-address=");
|
||||||
|
addr.s_addr = nm_ip4_address_get_address (tmp);
|
||||||
|
if (!inet_ntop (AF_INET, &addr, &localaddr[0], INET_ADDRSTRLEN)) {
|
||||||
|
nm_log_warn (LOGD_SHARING, "error converting IP4 address 0x%X",
|
||||||
|
ntohl (addr.s_addr));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
g_string_append (s, localaddr);
|
||||||
|
nm_cmd_line_add_string (cmd, s->str);
|
||||||
|
g_string_free (s, TRUE);
|
||||||
|
return cmd;
|
||||||
|
|
||||||
|
error:
|
||||||
|
nm_cmd_line_destroy (cmd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline const char *
|
||||||
|
find_dnsmasq (void)
|
||||||
|
{
|
||||||
|
static const char *paths[] = {
|
||||||
|
"/usr/local/sbin/dnsmasq",
|
||||||
|
"/usr/sbin/dnsmasq",
|
||||||
|
"/sbin/dnsmasq",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
const char **binary = paths;
|
||||||
|
|
||||||
|
while (*binary != NULL) {
|
||||||
|
if (g_file_test (*binary, G_FILE_TEST_EXISTS))
|
||||||
|
return *binary;
|
||||||
|
binary++;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
add_ip4_config (GString *str, NMIP4Config *ip4, gboolean split)
|
||||||
|
{
|
||||||
|
char buf[INET_ADDRSTRLEN + 1];
|
||||||
|
struct in_addr addr;
|
||||||
|
int n, i;
|
||||||
|
|
||||||
|
/* FIXME: it appears that dnsmasq can only handle one nameserver
|
||||||
|
* per domain (at the manpage seems to indicate that) so only use
|
||||||
|
* the first nameserver here.
|
||||||
|
*/
|
||||||
|
addr.s_addr = nm_ip4_config_get_nameserver (ip4, 0);
|
||||||
|
memset (&buf[0], 0, sizeof (buf));
|
||||||
|
if (!inet_ntop (AF_INET, &addr, buf, sizeof (buf)))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* searches are preferred over domains */
|
||||||
|
n = nm_ip4_config_get_num_searches (ip4);
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
g_string_append_printf (str, "server=%s%s%s%s\n",
|
||||||
|
split ? "/" : "",
|
||||||
|
split ? nm_ip4_config_get_search (ip4, i) : "",
|
||||||
|
split ? "/" : "",
|
||||||
|
buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n == 0) {
|
||||||
|
/* If not searches, use any domains */
|
||||||
|
n = nm_ip4_config_get_num_domains (ip4);
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
g_string_append_printf (str, "server=%s%s%s%s\n",
|
||||||
|
split ? "/" : "",
|
||||||
|
split ? nm_ip4_config_get_domain (ip4, i) : "",
|
||||||
|
split ? "/" : "",
|
||||||
|
buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
add_ip6_config (GString *str, NMIP6Config *ip6, gboolean split)
|
||||||
|
{
|
||||||
|
char buf[INET6_ADDRSTRLEN + 1];
|
||||||
|
const struct in6_addr *addr;
|
||||||
|
int n, i;
|
||||||
|
|
||||||
|
/* FIXME: it appears that dnsmasq can only handle one nameserver
|
||||||
|
* per domain (at the manpage seems to indicate that) so only use
|
||||||
|
* the first nameserver here.
|
||||||
|
*/
|
||||||
|
addr = nm_ip6_config_get_nameserver (ip6, 0);
|
||||||
|
memset (&buf[0], 0, sizeof (buf));
|
||||||
|
|
||||||
|
/* inet_ntop is probably supposed to do this for us, but it doesn't */
|
||||||
|
if (IN6_IS_ADDR_V4MAPPED (addr)) {
|
||||||
|
if (!inet_ntop (AF_INET, &(addr->s6_addr32[3]), buf, sizeof (buf)))
|
||||||
|
return FALSE;
|
||||||
|
} else {
|
||||||
|
if (!inet_ntop (AF_INET6, addr, buf, sizeof (buf)))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* searches are preferred over domains */
|
||||||
|
n = nm_ip6_config_get_num_searches (ip6);
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
g_string_append_printf (str, "server=%s%s%s%s\n",
|
||||||
|
split ? "/" : "",
|
||||||
|
split ? nm_ip6_config_get_search (ip6, i) : "",
|
||||||
|
split ? "/" : "",
|
||||||
|
buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n == 0) {
|
||||||
|
/* If not searches, use any domains */
|
||||||
|
n = nm_ip6_config_get_num_domains (ip6);
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
g_string_append_printf (str, "server=%s%s%s%s\n",
|
||||||
|
split ? "/" : "",
|
||||||
|
split ? nm_ip6_config_get_domain (ip6, i) : "",
|
||||||
|
split ? "/" : "",
|
||||||
|
buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
update (NMDnsPlugin *plugin,
|
||||||
|
const GSList *vpn_configs,
|
||||||
|
const GSList *dev_configs,
|
||||||
|
const GSList *other_configs,
|
||||||
|
const char *hostname)
|
||||||
|
{
|
||||||
|
NMDnsDnsmasq *self = NM_DNS_DNSMASQ (plugin);
|
||||||
|
NMDnsDnsmasqPrivate *priv = NM_DNS_DNSMASQ_GET_PRIVATE (self);
|
||||||
|
GString *conf;
|
||||||
|
GSList *iter;
|
||||||
|
const char *argv[10];
|
||||||
|
GError *error = NULL;
|
||||||
|
int ignored;
|
||||||
|
|
||||||
|
/* Build up the new dnsmasq config file */
|
||||||
|
conf = g_string_sized_new (150);
|
||||||
|
|
||||||
|
/* Use split DNS for VPN configs */
|
||||||
|
for (iter = (GSList *) vpn_configs; iter; iter = g_slist_next (iter)) {
|
||||||
|
if (NM_IS_IP4_CONFIG (iter->data))
|
||||||
|
add_ip4_config (conf, NM_IP4_CONFIG (iter->data), TRUE);
|
||||||
|
else if (NM_IS_IP6_CONFIG (iter->data))
|
||||||
|
add_ip6_config (conf, NM_IP6_CONFIG (iter->data), TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now add interface configs without split DNS */
|
||||||
|
for (iter = (GSList *) dev_configs; iter;iter = g_slist_next (iter)) {
|
||||||
|
if (NM_IS_IP4_CONFIG (iter->data))
|
||||||
|
add_ip4_config (conf, NM_IP4_CONFIG (iter->data), FALSE);
|
||||||
|
else if (NM_IS_IP6_CONFIG (iter->data))
|
||||||
|
add_ip6_config (conf, NM_IP6_CONFIG (iter->data), FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* And any other random configs */
|
||||||
|
for (iter = (GSList *) other_configs; iter;iter = g_slist_next (iter)) {
|
||||||
|
if (NM_IS_IP4_CONFIG (iter->data))
|
||||||
|
add_ip4_config (conf, NM_IP4_CONFIG (iter->data), FALSE);
|
||||||
|
else if (NM_IS_IP6_CONFIG (iter->data))
|
||||||
|
add_ip6_config (conf, NM_IP6_CONFIG (iter->data), FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write out the config file */
|
||||||
|
if (!g_file_set_contents (CONFFILE, conf->str, -1, &error)) {
|
||||||
|
nm_log_warn (LOGD_DNS, "Failed to write dnsmasq config file %s: (%d) %s",
|
||||||
|
CONFFILE,
|
||||||
|
error ? error->code : -1,
|
||||||
|
error && error->message ? error->message : "(unknown)");
|
||||||
|
g_clear_error (&error);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
ignored = chmod (CONFFILE, 0600);
|
||||||
|
|
||||||
|
nm_log_dbg (LOGD_DNS, "dnsmasq local caching DNS configuration:");
|
||||||
|
nm_log_dbg (LOGD_DNS, "%s", conf->str);
|
||||||
|
|
||||||
|
argv[0] = find_dnsmasq ();
|
||||||
|
argv[1] = "--no-resolv"; /* Use only commandline */
|
||||||
|
argv[2] = "--keep-in-foreground";
|
||||||
|
argv[3] = "--pid-file=" PIDFILE;
|
||||||
|
argv[4] = "--listen-address=127.0.0.1"; /* Should work for both 4 and 6 */
|
||||||
|
argv[5] = "--conf-file=" CONFFILE;
|
||||||
|
argv[6] = NULL;
|
||||||
|
|
||||||
|
/* And finally spawn dnsmasq */
|
||||||
|
priv->pid = nm_dns_plugin_child_spawn (NM_DNS_PLUGIN (self), argv, PIDFILE, "bin/dnsmasq");
|
||||||
|
|
||||||
|
out:
|
||||||
|
g_string_free (conf, TRUE);
|
||||||
|
return priv->pid ? TRUE : FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************/
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
dm_exit_code_to_msg (int status)
|
||||||
|
{
|
||||||
|
if (status == 1)
|
||||||
|
return "Configuration problem";
|
||||||
|
else if (status == 2)
|
||||||
|
return "Network access problem (address in use; permissions; etc)";
|
||||||
|
else if (status == 3)
|
||||||
|
return "Filesystem problem (missing file/directory; permissions; etc)";
|
||||||
|
else if (status == 4)
|
||||||
|
return "Memory allocation failure";
|
||||||
|
else if (status == 5)
|
||||||
|
return "Other problem";
|
||||||
|
else if (status >= 11)
|
||||||
|
return "Lease-script 'init' process failure";
|
||||||
|
return "Unknown error";
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
child_quit (NMDnsPlugin *plugin, gint status)
|
||||||
|
{
|
||||||
|
NMDnsDnsmasq *self = NM_DNS_DNSMASQ (plugin);
|
||||||
|
NMDnsDnsmasqPrivate *priv = NM_DNS_DNSMASQ_GET_PRIVATE (self);
|
||||||
|
gboolean failed = TRUE;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (WIFEXITED (status)) {
|
||||||
|
err = WEXITSTATUS (status);
|
||||||
|
if (err) {
|
||||||
|
nm_log_warn (LOGD_DNS, "dnsmasq exited with error: %s (%d)",
|
||||||
|
dm_exit_code_to_msg (err),
|
||||||
|
err);
|
||||||
|
} else
|
||||||
|
failed = FALSE;
|
||||||
|
} else if (WIFSTOPPED (status)) {
|
||||||
|
nm_log_warn (LOGD_DNS, "dnsmasq stopped unexpectedly with signal %d", WSTOPSIG (status));
|
||||||
|
} else if (WIFSIGNALED (status)) {
|
||||||
|
nm_log_warn (LOGD_DNS, "dnsmasq died with signal %d", WTERMSIG (status));
|
||||||
|
} else {
|
||||||
|
nm_log_warn (LOGD_DNS, "dnsmasq died from an unknown cause");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (failed)
|
||||||
|
g_signal_emit_by_name (self, NM_DNS_PLUGIN_FAILED);
|
||||||
|
|
||||||
|
priv->pid = 0;
|
||||||
|
unlink (CONFFILE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************/
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
init (NMDnsPlugin *plugin)
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
is_exclusive (NMDnsPlugin *plugin)
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************/
|
||||||
|
|
||||||
|
NMDnsDnsmasq *
|
||||||
|
nm_dns_dnsmasq_new (void)
|
||||||
|
{
|
||||||
|
return (NMDnsDnsmasq *) g_object_new (NM_TYPE_DNS_DNSMASQ, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
nm_dns_dnsmasq_init (NMDnsDnsmasq *self)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
nm_dns_dnsmasq_class_init (NMDnsDnsmasqClass *dns_class)
|
||||||
|
{
|
||||||
|
NMDnsPluginClass *plugin_class = NM_DNS_PLUGIN_CLASS (dns_class);
|
||||||
|
|
||||||
|
g_type_class_add_private (dns_class, sizeof (NMDnsDnsmasqPrivate));
|
||||||
|
|
||||||
|
plugin_class->init = init;
|
||||||
|
plugin_class->child_quit = child_quit;
|
||||||
|
plugin_class->is_exclusive = is_exclusive;
|
||||||
|
plugin_class->update = update;
|
||||||
|
}
|
||||||
|
|
47
src/dns-manager/nm-dns-dnsmasq.h
Normal file
47
src/dns-manager/nm-dns-dnsmasq.h
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
||||||
|
/* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Red Hat, Inc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NM_DNS_DNSMASQ_H
|
||||||
|
#define NM_DNS_DNSMASQ_H
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
#include "nm-dns-plugin.h"
|
||||||
|
|
||||||
|
#define NM_TYPE_DNS_DNSMASQ (nm_dns_dnsmasq_get_type ())
|
||||||
|
#define NM_DNS_DNSMASQ(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DNS_DNSMASQ, NMDnsDnsmasq))
|
||||||
|
#define NM_DNS_DNSMASQ_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DNS_DNSMASQ, NMDnsDnsmasqClass))
|
||||||
|
#define NM_IS_DNS_DNSMASQ(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DNS_DNSMASQ))
|
||||||
|
#define NM_IS_DNS_DNSMASQ_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_DNS_DNSMASQ))
|
||||||
|
#define NM_DNS_DNSMASQ_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DNS_DNSMASQ, NMDnsDnsmasqClass))
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
NMDnsPlugin parent;
|
||||||
|
} NMDnsDnsmasq;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
NMDnsPluginClass parent;
|
||||||
|
} NMDnsDnsmasqClass;
|
||||||
|
|
||||||
|
GType nm_dns_dnsmasq_get_type (void);
|
||||||
|
|
||||||
|
NMDnsDnsmasq *nm_dns_dnsmasq_new (void);
|
||||||
|
|
||||||
|
#endif /* NM_DNS_DNSMASQ_H */
|
||||||
|
|
@@ -43,6 +43,8 @@
|
|||||||
#include "nm-system.h"
|
#include "nm-system.h"
|
||||||
#include "NetworkManagerUtils.h"
|
#include "NetworkManagerUtils.h"
|
||||||
|
|
||||||
|
#include "nm-dns-dnsmasq.h"
|
||||||
|
|
||||||
#ifdef HAVE_SELINUX
|
#ifdef HAVE_SELINUX
|
||||||
#include <selinux/selinux.h>
|
#include <selinux/selinux.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -828,12 +830,6 @@ nm_dns_manager_set_hostname (NMDnsManager *mgr,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static GObject *
|
|
||||||
nm_dns_dnsmasq_new (void)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static GObject *
|
static GObject *
|
||||||
nm_dns_bind_new (void)
|
nm_dns_bind_new (void)
|
||||||
{
|
{
|
||||||
@@ -850,18 +846,18 @@ static void
|
|||||||
load_plugins (NMDnsManager *self, const char **plugins)
|
load_plugins (NMDnsManager *self, const char **plugins)
|
||||||
{
|
{
|
||||||
NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self);
|
NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self);
|
||||||
GObject *plugin;
|
NMDnsPlugin *plugin;
|
||||||
const char **iter;
|
const char **iter;
|
||||||
|
|
||||||
if (plugins && *plugins) {
|
if (plugins && *plugins) {
|
||||||
/* Create each configured plugin */
|
/* Create each configured plugin */
|
||||||
for (iter = plugins; iter && *iter; iter++) {
|
for (iter = plugins; iter && *iter; iter++) {
|
||||||
if (!strcasecmp (*iter, "dnsmasq"))
|
if (!strcasecmp (*iter, "dnsmasq"))
|
||||||
plugin = nm_dns_dnsmasq_new ();
|
plugin = NM_DNS_PLUGIN (nm_dns_dnsmasq_new ());
|
||||||
else if (!strcasecmp (*iter, "bind"))
|
else if (!strcasecmp (*iter, "bind"))
|
||||||
plugin = nm_dns_bind_new ();
|
plugin = NM_DNS_PLUGIN (nm_dns_bind_new ());
|
||||||
else if (!strcasecmp (*iter, "chromium"))
|
else if (!strcasecmp (*iter, "chromium"))
|
||||||
plugin = nm_dns_chromium_new ();
|
plugin = NM_DNS_PLUGIN (nm_dns_chromium_new ());
|
||||||
else {
|
else {
|
||||||
nm_log_warn (LOGD_DNS, "Unknown DNS plugin '%s'", *iter);
|
nm_log_warn (LOGD_DNS, "Unknown DNS plugin '%s'", *iter);
|
||||||
}
|
}
|
||||||
@@ -873,7 +869,7 @@ load_plugins (NMDnsManager *self, const char **plugins)
|
|||||||
/* Create default plugins */
|
/* Create default plugins */
|
||||||
|
|
||||||
/* Chromium support */
|
/* Chromium support */
|
||||||
plugin = nm_dns_chromium_new ();
|
plugin = NM_DNS_PLUGIN (nm_dns_chromium_new ());
|
||||||
g_assert (plugin);
|
g_assert (plugin);
|
||||||
priv->plugins = g_slist_append (priv->plugins, plugin);
|
priv->plugins = g_slist_append (priv->plugins, plugin);
|
||||||
}
|
}
|
||||||
|
311
src/dns-manager/nm-dns-plugin.c
Normal file
311
src/dns-manager/nm-dns-plugin.c
Normal file
@@ -0,0 +1,311 @@
|
|||||||
|
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
||||||
|
/* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
#include "nm-dns-plugin.h"
|
||||||
|
#include "nm-logging.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
gboolean disposed;
|
||||||
|
|
||||||
|
GPid pid;
|
||||||
|
guint32 watch_id;
|
||||||
|
char *progname;
|
||||||
|
char *pidfile;
|
||||||
|
} NMDnsPluginPrivate;
|
||||||
|
|
||||||
|
#define NM_DNS_PLUGIN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DNS_PLUGIN, NMDnsPluginPrivate))
|
||||||
|
|
||||||
|
G_DEFINE_TYPE_EXTENDED (NMDnsPlugin, nm_dns_plugin, G_TYPE_OBJECT, G_TYPE_FLAG_ABSTRACT, {})
|
||||||
|
|
||||||
|
enum {
|
||||||
|
FAILED,
|
||||||
|
CHILD_QUIT,
|
||||||
|
LAST_SIGNAL
|
||||||
|
};
|
||||||
|
static guint signals[LAST_SIGNAL] = { 0 };
|
||||||
|
|
||||||
|
/********************************************/
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
nm_dns_plugin_update (NMDnsPlugin *self,
|
||||||
|
const GSList *vpn_configs,
|
||||||
|
const GSList *dev_configs,
|
||||||
|
const GSList *other_configs,
|
||||||
|
const char *hostname)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (NM_DNS_PLUGIN_GET_CLASS (self)->update != NULL, FALSE);
|
||||||
|
|
||||||
|
return NM_DNS_PLUGIN_GET_CLASS (self)->update (self,
|
||||||
|
vpn_configs,
|
||||||
|
dev_configs,
|
||||||
|
other_configs,
|
||||||
|
hostname);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
is_exclusive (NMDnsPlugin *self)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
nm_dns_plugin_is_exclusive (NMDnsPlugin *self)
|
||||||
|
{
|
||||||
|
return NM_DNS_PLUGIN_GET_CLASS (self)->is_exclusive (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************/
|
||||||
|
|
||||||
|
static void
|
||||||
|
kill_existing (const char *progname, const char *pidfile, const char *kill_match)
|
||||||
|
{
|
||||||
|
char *contents = NULL;
|
||||||
|
glong pid;
|
||||||
|
char *proc_path = NULL;
|
||||||
|
char *cmdline_contents = NULL;
|
||||||
|
|
||||||
|
if (!g_file_get_contents (pidfile, &contents, NULL, NULL))
|
||||||
|
return;
|
||||||
|
|
||||||
|
pid = strtol (contents, NULL, 10);
|
||||||
|
if (pid < 1 || pid > INT_MAX)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
proc_path = g_strdup_printf ("/proc/%ld/cmdline", pid);
|
||||||
|
if (!g_file_get_contents (proc_path, &cmdline_contents, NULL, NULL))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (strstr (cmdline_contents, kill_match)) {
|
||||||
|
if (kill (pid, 0)) {
|
||||||
|
nm_log_dbg (LOGD_DNS, "Killing stale %s child process %ld", progname, pid);
|
||||||
|
kill (pid, SIGKILL);
|
||||||
|
}
|
||||||
|
unlink (pidfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
g_free (cmdline_contents);
|
||||||
|
g_free (proc_path);
|
||||||
|
g_free (contents);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
watch_cb (GPid pid, gint status, gpointer user_data)
|
||||||
|
{
|
||||||
|
NMDnsPlugin *self = NM_DNS_PLUGIN (user_data);
|
||||||
|
NMDnsPluginPrivate *priv = NM_DNS_PLUGIN_GET_PRIVATE (self);
|
||||||
|
|
||||||
|
priv->pid = 0;
|
||||||
|
g_free (priv->progname);
|
||||||
|
priv->progname = NULL;
|
||||||
|
|
||||||
|
g_signal_emit (self, signals[CHILD_QUIT], 0, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
child_setup (gpointer user_data G_GNUC_UNUSED)
|
||||||
|
{
|
||||||
|
/* We are in the child process at this point */
|
||||||
|
pid_t pid = getpid ();
|
||||||
|
setpgid (pid, pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
GPid
|
||||||
|
nm_dns_plugin_child_spawn (NMDnsPlugin *self,
|
||||||
|
const char **argv,
|
||||||
|
const char *pidfile,
|
||||||
|
const char *kill_match)
|
||||||
|
{
|
||||||
|
NMDnsPluginPrivate *priv = NM_DNS_PLUGIN_GET_PRIVATE (self);
|
||||||
|
GError *error = NULL;
|
||||||
|
char *cmdline;
|
||||||
|
|
||||||
|
g_return_val_if_fail (argv != NULL, 0);
|
||||||
|
g_return_val_if_fail (argv[0] != NULL, 0);
|
||||||
|
|
||||||
|
g_warn_if_fail (priv->progname == NULL);
|
||||||
|
g_free (priv->progname);
|
||||||
|
priv->progname = g_path_get_basename (argv[0]);
|
||||||
|
|
||||||
|
if (pidfile) {
|
||||||
|
g_return_val_if_fail (kill_match != NULL, 0);
|
||||||
|
kill_existing (priv->progname, pidfile, kill_match);
|
||||||
|
|
||||||
|
g_free (priv->pidfile);
|
||||||
|
priv->pidfile = g_strdup (pidfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
nm_log_info (LOGD_DNS, "Starting %s...", priv->progname);
|
||||||
|
cmdline = g_strjoinv (" ", (char **) argv);
|
||||||
|
nm_log_dbg (LOGD_DNS, "Command line: %s", cmdline);
|
||||||
|
g_free (cmdline);
|
||||||
|
|
||||||
|
priv->pid = 0;
|
||||||
|
if (g_spawn_async (NULL, (char **) argv, NULL,
|
||||||
|
G_SPAWN_DO_NOT_REAP_CHILD,
|
||||||
|
child_setup,
|
||||||
|
NULL, &priv->pid,
|
||||||
|
&error)) {
|
||||||
|
nm_log_dbg (LOGD_DNS, "%s started with pid %d", priv->progname, priv->pid);
|
||||||
|
priv->watch_id = g_child_watch_add (priv->pid, (GChildWatchFunc) watch_cb, self);
|
||||||
|
} else {
|
||||||
|
nm_log_warn (LOGD_DNS, "Failed to spawn %s: (%d) %s",
|
||||||
|
priv->progname, error ? error->code : -1,
|
||||||
|
error && error->message ? error->message : "(unknown)");
|
||||||
|
g_clear_error (&error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return priv->pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int pid;
|
||||||
|
char *progname;
|
||||||
|
} KillInfo;
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
ensure_killed (gpointer data)
|
||||||
|
{
|
||||||
|
KillInfo *info = data;
|
||||||
|
|
||||||
|
if (kill (info->pid, 0) == 0)
|
||||||
|
kill (info->pid, SIGKILL);
|
||||||
|
|
||||||
|
/* ensure the child is reaped */
|
||||||
|
nm_log_dbg (LOGD_DNS, "waiting for %s pid %d to exit", info->progname, info->pid);
|
||||||
|
waitpid (info->pid, NULL, 0);
|
||||||
|
nm_log_dbg (LOGD_DNS, "dnsmasq pid %d cleaned up", info->progname, info->pid);
|
||||||
|
|
||||||
|
g_free (info->progname);
|
||||||
|
g_free (info);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean nm_dns_plugin_child_kill (NMDnsPlugin *self)
|
||||||
|
{
|
||||||
|
NMDnsPluginPrivate *priv = NM_DNS_PLUGIN_GET_PRIVATE (self);
|
||||||
|
|
||||||
|
if (priv->watch_id) {
|
||||||
|
g_source_remove (priv->watch_id);
|
||||||
|
priv->watch_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->pid) {
|
||||||
|
KillInfo *info;
|
||||||
|
|
||||||
|
if (kill (priv->pid, SIGTERM) == 0) {
|
||||||
|
info = g_malloc0 (sizeof (KillInfo));
|
||||||
|
info->pid = priv->pid;
|
||||||
|
info->progname = g_strdup (priv->progname);
|
||||||
|
g_timeout_add_seconds (2, ensure_killed, info);
|
||||||
|
} else {
|
||||||
|
kill (priv->pid, SIGKILL);
|
||||||
|
|
||||||
|
/* ensure the child is reaped */
|
||||||
|
nm_log_dbg (LOGD_DNS, "waiting for %s pid %d to exit", priv->progname, priv->pid);
|
||||||
|
waitpid (priv->pid, NULL, 0);
|
||||||
|
nm_log_dbg (LOGD_DNS, "%s pid %d cleaned up", priv->progname, priv->pid);
|
||||||
|
}
|
||||||
|
priv->pid = 0;
|
||||||
|
g_free (priv->progname);
|
||||||
|
priv->progname = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->pidfile) {
|
||||||
|
unlink (priv->pidfile);
|
||||||
|
g_free (priv->pidfile);
|
||||||
|
priv->pidfile = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************/
|
||||||
|
|
||||||
|
static void
|
||||||
|
nm_dns_plugin_init (NMDnsPlugin *self)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dispose (GObject *object)
|
||||||
|
{
|
||||||
|
NMDnsPlugin *self = NM_DNS_PLUGIN (object);
|
||||||
|
NMDnsPluginPrivate *priv = NM_DNS_PLUGIN_GET_PRIVATE (self);
|
||||||
|
|
||||||
|
if (!priv->disposed) {
|
||||||
|
priv->disposed = TRUE;
|
||||||
|
|
||||||
|
nm_dns_plugin_child_kill (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (nm_dns_plugin_parent_class)->dispose (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
finalize (GObject *object)
|
||||||
|
{
|
||||||
|
NMDnsPlugin *self = NM_DNS_PLUGIN (object);
|
||||||
|
NMDnsPluginPrivate *priv = NM_DNS_PLUGIN_GET_PRIVATE (self);
|
||||||
|
|
||||||
|
g_free (priv->progname);
|
||||||
|
g_free (priv->pidfile);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (nm_dns_plugin_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
nm_dns_plugin_class_init (NMDnsPluginClass *plugin_class)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (plugin_class);
|
||||||
|
|
||||||
|
g_type_class_add_private (plugin_class, sizeof (NMDnsPluginPrivate));
|
||||||
|
|
||||||
|
/* virtual methods */
|
||||||
|
object_class->dispose = dispose;
|
||||||
|
object_class->finalize = finalize;
|
||||||
|
plugin_class->is_exclusive = is_exclusive;
|
||||||
|
|
||||||
|
/* signals */
|
||||||
|
signals[FAILED] =
|
||||||
|
g_signal_new (NM_DNS_PLUGIN_FAILED,
|
||||||
|
G_OBJECT_CLASS_TYPE (object_class),
|
||||||
|
G_SIGNAL_RUN_FIRST,
|
||||||
|
G_STRUCT_OFFSET (NMDnsPluginClass, failed),
|
||||||
|
NULL, NULL,
|
||||||
|
g_cclosure_marshal_VOID__VOID,
|
||||||
|
G_TYPE_NONE, 0);
|
||||||
|
|
||||||
|
signals[CHILD_QUIT] =
|
||||||
|
g_signal_new (NM_DNS_PLUGIN_CHILD_QUIT,
|
||||||
|
G_OBJECT_CLASS_TYPE (object_class),
|
||||||
|
G_SIGNAL_RUN_FIRST,
|
||||||
|
G_STRUCT_OFFSET (NMDnsPluginClass, child_quit),
|
||||||
|
NULL, NULL,
|
||||||
|
g_cclosure_marshal_VOID__INT,
|
||||||
|
G_TYPE_NONE, 1, G_TYPE_INT);
|
||||||
|
}
|
||||||
|
|
107
src/dns-manager/nm-dns-plugin.h
Normal file
107
src/dns-manager/nm-dns-plugin.h
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
||||||
|
/* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Red Hat, Inc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NM_DNS_PLUGIN_H
|
||||||
|
#define NM_DNS_PLUGIN_H
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
#define NM_TYPE_DNS_PLUGIN (nm_dns_plugin_get_type ())
|
||||||
|
#define NM_DNS_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DNS_PLUGIN, NMDnsPlugin))
|
||||||
|
#define NM_DNS_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DNS_PLUGIN, NMDnsPluginClass))
|
||||||
|
#define NM_IS_DNS_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DNS_PLUGIN))
|
||||||
|
#define NM_IS_DNS_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_DNS_PLUGIN))
|
||||||
|
#define NM_DNS_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DNS_PLUGIN, NMDnsPluginClass))
|
||||||
|
|
||||||
|
#define NM_DNS_PLUGIN_FAILED "failed"
|
||||||
|
#define NM_DNS_PLUGIN_CHILD_QUIT "child-quit"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GObject parent;
|
||||||
|
} NMDnsPlugin;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GObjectClass parent;
|
||||||
|
|
||||||
|
/* Methods */
|
||||||
|
gboolean (*init) (NMDnsPlugin *self);
|
||||||
|
|
||||||
|
/* Called when DNS information is changed. 'vpn_configs' is a list of
|
||||||
|
* NMIP4Config or NMIP6Config objects from VPN connections, while
|
||||||
|
* 'dev_configs' is a list of NMPI4Config or NMIP6Config objects from
|
||||||
|
* active devices. 'other_configs' represent other IP configuration that
|
||||||
|
* may be in-use. Configs of the same IP version are sorted in priority
|
||||||
|
* order.
|
||||||
|
*/
|
||||||
|
gboolean (*update) (NMDnsPlugin *self,
|
||||||
|
const GSList *vpn_configs,
|
||||||
|
const GSList *dev_configs,
|
||||||
|
const GSList *other_configs,
|
||||||
|
const char *hostname);
|
||||||
|
|
||||||
|
/* Subclasses should override and return TRUE if they start a local
|
||||||
|
* caching nameserver that listens on localhost and would block any
|
||||||
|
* other local caching nameserver from operating.
|
||||||
|
*/
|
||||||
|
gboolean (*is_exclusive) (NMDnsPlugin *self);
|
||||||
|
|
||||||
|
/* Signals */
|
||||||
|
|
||||||
|
/* Emitted by the plugin and consumed by NMDnsManager when
|
||||||
|
* some error happens with the nameserver subprocess. Causes NM to fall
|
||||||
|
* back to writing out a non-local-caching resolv.conf until the next
|
||||||
|
* DNS update.
|
||||||
|
*/
|
||||||
|
void (*failed) (NMDnsPlugin *self);
|
||||||
|
|
||||||
|
/* Emitted by the plugin base class when the nameserver subprocess
|
||||||
|
* quits. This signal is consumed by the plugin subclasses and not
|
||||||
|
* by NMDnsManager. If the subclass decides the exit status (as returned
|
||||||
|
* by waitpid(2)) is fatal it should then emit the 'failed' signal.
|
||||||
|
*/
|
||||||
|
void (*child_quit) (NMDnsPlugin *self, gint status);
|
||||||
|
} NMDnsPluginClass;
|
||||||
|
|
||||||
|
GType nm_dns_plugin_get_type (void);
|
||||||
|
|
||||||
|
gboolean nm_dns_plugin_is_exclusive (NMDnsPlugin *self);
|
||||||
|
|
||||||
|
gboolean nm_dns_plugin_update (NMDnsPlugin *self,
|
||||||
|
const GSList *vpn_configs,
|
||||||
|
const GSList *dev_configs,
|
||||||
|
const GSList *other_configs,
|
||||||
|
const char *hostname);
|
||||||
|
|
||||||
|
/* For subclasses/plugins */
|
||||||
|
|
||||||
|
/* Spawn a child process and watch for it to quit. 'argv' is the NULL-terminated
|
||||||
|
* argument vector to spawn the child with, where argv[0] is the full path to
|
||||||
|
* the child's executable. If 'pidfile' is given the process owning the PID
|
||||||
|
* contained in 'pidfile' will be killed if its command line matches 'kill_match'
|
||||||
|
* and the pidfile will be deleted.
|
||||||
|
*/
|
||||||
|
GPid nm_dns_plugin_child_spawn (NMDnsPlugin *self,
|
||||||
|
const char **argv,
|
||||||
|
const char *pidfile,
|
||||||
|
const char *kill_match);
|
||||||
|
|
||||||
|
gboolean nm_dns_plugin_child_kill (NMDnsPlugin *self);
|
||||||
|
|
||||||
|
#endif /* NM_DNS_PLUGIN_H */
|
||||||
|
|
Reference in New Issue
Block a user