Commit 35c83138 authored by Thomas Haller's avatar Thomas Haller

dns: merge branch 'th/dnsmasq-rework'

!254
parents e2846081 93d5efb4
Pipeline #66571 passed with stages
in 66 minutes and 29 seconds
......@@ -556,6 +556,17 @@ _nm_g_value_unset (GValue *value)
#define g_value_unset _nm_g_value_unset
#endif
/* G_PID_FORMAT was added only in 2.53.5. Define it ourself.
*
* If this was about "pid_t", we would check SIZEOF_PID_T, and set
* PRIi32/PRIi16, like systemd does. But it's actually about
* GPid, which glib typedefs as an "int".
*
* There is a test_gpid() that check that GPid is really a typedef
* for int. */
#undef G_PID_FORMAT
#define G_PID_FORMAT "i"
/*****************************************************************************/
#endif /* __NM_GLIB_H__ */
......@@ -2681,7 +2681,9 @@ nm_utils_get_start_time_for_pid (pid_t pid, char *out_state, pid_t *out_ppid)
g_return_val_if_fail (pid > 0, 0);
nm_sprintf_buf (filename, "/proc/%"G_GUINT64_FORMAT"/stat", (guint64) pid);
G_STATIC_ASSERT_EXPR (sizeof (GPid) >= sizeof (pid_t));
nm_sprintf_buf (filename, "/proc/%"G_PID_FORMAT"/stat", (GPid) pid);
if (!g_file_get_contents (filename, &contents, &length, NULL))
goto fail;
......
......@@ -1154,6 +1154,15 @@ nm_utils_dbus_normalize_object_path (const char *path)
guint64 nm_utils_get_start_time_for_pid (pid_t pid, char *out_state, pid_t *out_ppid);
static inline gboolean
nm_utils_process_state_is_dead (char pstate)
{
/* "/proc/[pid]/stat" returns a state as the 3rd fields (see `man 5 proc`).
* Some of these states indicate the the process is effectively dead (or a zombie).
*/
return NM_IN_SET (pstate, 'Z', 'x', 'X');
}
/*****************************************************************************/
gpointer _nm_utils_user_data_pack (int nargs, gconstpointer *args);
......
......@@ -15,6 +15,31 @@
/*****************************************************************************/
static void
test_gpid (void)
{
const int *int_ptr;
GPid pid = 42;
/* We redefine G_PID_FORMAT, because it's only available since glib 2.53.5.
*
* Also, this is the format for GPid, which for glib is always a typedef
* for "int". Add a check for that here.
*
* G_PID_FORMAT is not about pid_t, which might be a smaller int, and which we would
* check with SIZEOF_PID_T. */
G_STATIC_ASSERT (sizeof (GPid) == sizeof (int));
g_assert_cmpstr (""G_PID_FORMAT, ==, "i");
/* check that it's really "int". We will get a compiler warning, if that's not
* the case. */
int_ptr = &pid;
g_assert_cmpint (*int_ptr, ==, 42);
}
/*****************************************************************************/
static void
test_monotonic_timestamp (void)
{
......@@ -502,6 +527,7 @@ int main (int argc, char **argv)
{
nmtst_init (&argc, &argv, TRUE);
g_test_add_func ("/general/test_gpid", test_gpid);
g_test_add_func ("/general/test_monotonic_timestamp", test_monotonic_timestamp);
g_test_add_func ("/general/test_nmhash", test_nmhash);
g_test_add_func ("/general/test_nm_make_strv", test_make_strv);
......
......@@ -981,6 +981,7 @@ _shutdown_waitobj_cb (gpointer user_data,
* nm_shutdown_wait_obj_register_full:
* @watched_obj: the object to watch. Takes a weak reference on the object
* to be notified when it gets destroyed.
* If wait_type is %NM_SHUTDOWN_WAIT_TYPE_HANDLE, this must be %NULL.
* @wait_type: whether @watched_obj is just a plain GObject or a GCancellable
* that should be cancelled.
* @msg_reason: a reason message, for debugging and logging purposes.
......@@ -1029,6 +1030,8 @@ nm_shutdown_wait_obj_register_full (gpointer watched_obj,
g_return_val_if_fail (G_IS_OBJECT (watched_obj), NULL);
else if (wait_type == NM_SHUTDOWN_WAIT_TYPE_CANCELLABLE)
g_return_val_if_fail (G_IS_CANCELLABLE (watched_obj), NULL);
else if (wait_type == NM_SHUTDOWN_WAIT_TYPE_HANDLE)
g_return_val_if_fail (!watched_obj, NULL);
else
g_return_val_if_reached (NULL);
......@@ -1046,7 +1049,8 @@ nm_shutdown_wait_obj_register_full (gpointer watched_obj,
.is_cancellable = (wait_type == NM_SHUTDOWN_WAIT_TYPE_CANCELLABLE),
};
c_list_link_tail (&_shutdown_waitobj_lst_head, &handle->lst);
g_object_weak_ref (watched_obj, _shutdown_waitobj_cb, handle);
if (watched_obj)
g_object_weak_ref (watched_obj, _shutdown_waitobj_cb, handle);
return handle;
}
......@@ -1055,10 +1059,11 @@ nm_shutdown_wait_obj_unregister (NMShutdownWaitObjHandle *handle)
{
g_return_if_fail (handle);
nm_assert (G_IS_OBJECT (handle->watched_obj));
nm_assert (!handle->watched_obj || G_IS_OBJECT (handle->watched_obj));
nm_assert (nm_c_list_contains_entry (&_shutdown_waitobj_lst_head, handle, lst));
g_object_weak_unref (handle->watched_obj, _shutdown_waitobj_cb, handle);
if (handle->watched_obj)
g_object_weak_unref (handle->watched_obj, _shutdown_waitobj_cb, handle);
_shutdown_waitobj_unregister (handle);
}
......
......@@ -75,6 +75,10 @@ NMPlatformRoutingRule *nm_ip_routing_rule_to_platform (const NMIPRoutingRule *ru
#define NM_SHUTDOWN_TIMEOUT_MS_WATCHDOG 500
typedef enum {
/* There is no watched_obj argument, and the shutdown is delayed until the user
* explicitly calls unregister on the returned handle. */
NM_SHUTDOWN_WAIT_TYPE_HANDLE,
/* The watched_obj argument is a GObject, and shutdown is delayed until the object
* gets destroyed (or unregistered). */
NM_SHUTDOWN_WAIT_TYPE_OBJECT,
......@@ -102,6 +106,15 @@ nm_shutdown_wait_obj_register_object_full (gpointer watched_obj,
#define nm_shutdown_wait_obj_register_object(watched_obj, msg_reason) nm_shutdown_wait_obj_register_object_full((watched_obj), (""msg_reason""), FALSE)
static inline NMShutdownWaitObjHandle *
nm_shutdown_wait_obj_register_handle_full (char *msg_reason,
gboolean free_msg_reason)
{
return nm_shutdown_wait_obj_register_full (NULL, NM_SHUTDOWN_WAIT_TYPE_HANDLE, msg_reason, free_msg_reason);
}
#define nm_shutdown_wait_obj_register_handle(msg_reason) nm_shutdown_wait_obj_register_handle_full((""msg_reason""), FALSE)
static inline NMShutdownWaitObjHandle *
nm_shutdown_wait_obj_register_cancellable_full (GCancellable *watched_obj,
char *msg_reason,
......
......@@ -70,7 +70,7 @@ typedef struct _NMDhcpClientPrivate {
bool use_fqdn:1;
} NMDhcpClientPrivate;
G_DEFINE_TYPE_EXTENDED (NMDhcpClient, nm_dhcp_client, G_TYPE_OBJECT, G_TYPE_FLAG_ABSTRACT, {})
G_DEFINE_ABSTRACT_TYPE (NMDhcpClient, nm_dhcp_client, G_TYPE_OBJECT)
#define NM_DHCP_CLIENT_GET_PRIVATE(self) _NM_GET_PRIVATE_PTR (self, NMDhcpClient, NM_IS_DHCP_CLIENT)
......
This diff is collapsed.
......@@ -50,10 +50,6 @@
#define NETCONFIG_PATH "/sbin/netconfig"
#endif
#define PLUGIN_RATELIMIT_INTERVAL 30
#define PLUGIN_RATELIMIT_BURST 5
#define PLUGIN_RATELIMIT_DELAY 300
/*****************************************************************************/
typedef enum {
......@@ -1428,13 +1424,15 @@ update_dns (NMDnsManager *self,
nm_dns_plugin_update (priv->sd_resolve_plugin,
global_config,
_ip_config_lst_head (self),
priv->hostname);
priv->hostname,
NULL);
}
/* Let any plugins do their thing first */
if (priv->plugin) {
NMDnsPlugin *plugin = priv->plugin;
const char *plugin_name = nm_dns_plugin_get_name (plugin);
gs_free_error GError *plugin_error = NULL;
if (nm_dns_plugin_is_caching (plugin)) {
if (no_caching) {
......@@ -1449,8 +1447,9 @@ update_dns (NMDnsManager *self,
if (!nm_dns_plugin_update (plugin,
global_config,
_ip_config_lst_head (self),
priv->hostname)) {
_LOGW ("update-dns: plugin %s update failed", plugin_name);
priv->hostname,
&plugin_error)) {
_LOGW ("update-dns: plugin %s update failed: %s", plugin_name, plugin_error->message);
/* If the plugin failed to update, we shouldn't write out a local
* caching DNS configuration to resolv.conf.
......@@ -1554,66 +1553,7 @@ update_dns (NMDnsManager *self,
return !update || result == SR_SUCCESS;
}
static void
plugin_failed (NMDnsPlugin *plugin, gpointer user_data)
{
NMDnsManager *self = NM_DNS_MANAGER (user_data);
GError *error = NULL;
/* Errors with non-caching plugins aren't fatal */
if (!nm_dns_plugin_is_caching (plugin))
return;
/* Disable caching until the next DNS update */
if (!update_dns (self, TRUE, &error)) {
_LOGW ("could not commit DNS changes: %s", error->message);
g_clear_error (&error);
}
}
static gboolean
plugin_child_quit_update_dns (gpointer user_data)
{
GError *error = NULL;
NMDnsManager *self = NM_DNS_MANAGER (user_data);
/* Let the plugin try to spawn the child again */
if (!update_dns (self, FALSE, &error)) {
_LOGW ("could not commit DNS changes: %s", error->message);
g_clear_error (&error);
}
return G_SOURCE_REMOVE;
}
static void
plugin_child_quit (NMDnsPlugin *plugin, int exit_status, gpointer user_data)
{
NMDnsManager *self = NM_DNS_MANAGER (user_data);
NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self);
gint64 ts = nm_utils_get_monotonic_timestamp_ms ();
_LOGW ("plugin %s child quit unexpectedly", nm_dns_plugin_get_name (plugin));
if ( !priv->plugin_ratelimit.ts
|| (ts - priv->plugin_ratelimit.ts) / 1000 > PLUGIN_RATELIMIT_INTERVAL) {
priv->plugin_ratelimit.ts = ts;
priv->plugin_ratelimit.num_restarts = 0;
} else {
priv->plugin_ratelimit.num_restarts++;
if (priv->plugin_ratelimit.num_restarts > PLUGIN_RATELIMIT_BURST) {
plugin_failed (plugin, self);
_LOGW ("plugin %s child respawning too fast, delaying update for %u seconds",
nm_dns_plugin_get_name (plugin), PLUGIN_RATELIMIT_DELAY);
priv->plugin_ratelimit.timer = g_timeout_add_seconds (PLUGIN_RATELIMIT_DELAY,
plugin_child_quit_update_dns,
self);
return;
}
}
plugin_child_quit_update_dns (self);
}
/*****************************************************************************/
static void
_ip_config_dns_priority_changed (gpointer config,
......@@ -1843,15 +1783,14 @@ _clear_plugin (NMDnsManager *self)
{
NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self);
priv->plugin_ratelimit.ts = 0;
nm_clear_g_source (&priv->plugin_ratelimit.timer);
if (priv->plugin) {
g_signal_handlers_disconnect_by_func (priv->plugin, plugin_failed, self);
g_signal_handlers_disconnect_by_func (priv->plugin, plugin_child_quit, self);
nm_dns_plugin_stop (priv->plugin);
g_clear_object (&priv->plugin);
return TRUE;
}
priv->plugin_ratelimit.ts = 0;
nm_clear_g_source (&priv->plugin_ratelimit.timer);
return FALSE;
}
......@@ -2070,12 +2009,6 @@ again:
} else if (nm_clear_g_object (&priv->sd_resolve_plugin))
systemd_resolved_changed = TRUE;
if ( plugin_changed
&& priv->plugin) {
g_signal_connect (priv->plugin, NM_DNS_PLUGIN_FAILED, G_CALLBACK (plugin_failed), self);
g_signal_connect (priv->plugin, NM_DNS_PLUGIN_CHILD_QUIT, G_CALLBACK (plugin_child_quit), self);
}
g_object_freeze_notify (G_OBJECT (self));
if (!nm_streq0 (priv->mode, mode)) {
......
......@@ -17,14 +17,6 @@
/*****************************************************************************/
enum {
FAILED,
CHILD_QUIT,
LAST_SIGNAL,
};
static guint signals[LAST_SIGNAL] = { 0 };
typedef struct _NMDnsPluginPrivate {
GPid pid;
guint watch_id;
......@@ -32,7 +24,7 @@ typedef struct _NMDnsPluginPrivate {
char *pidfile;
} NMDnsPluginPrivate;
G_DEFINE_TYPE_EXTENDED (NMDnsPlugin, nm_dns_plugin, G_TYPE_OBJECT, G_TYPE_FLAG_ABSTRACT, {})
G_DEFINE_ABSTRACT_TYPE (NMDnsPlugin, nm_dns_plugin, G_TYPE_OBJECT)
#define NM_DNS_PLUGIN_GET_PRIVATE(self) _NM_GET_PRIVATE_PTR (self, NMDnsPlugin, NM_IS_DNS_PLUGIN)
......@@ -64,188 +56,46 @@ gboolean
nm_dns_plugin_update (NMDnsPlugin *self,
const NMGlobalDnsConfig *global_config,
const CList *ip_config_lst_head,
const char *hostname)
const char *hostname,
GError **error)
{
g_return_val_if_fail (NM_DNS_PLUGIN_GET_CLASS (self)->update != NULL, FALSE);
return NM_DNS_PLUGIN_GET_CLASS (self)->update (self,
global_config,
ip_config_lst_head,
hostname);
}
static gboolean
is_caching (NMDnsPlugin *self)
{
return FALSE;
hostname,
error);
}
gboolean
nm_dns_plugin_is_caching (NMDnsPlugin *self)
{
return NM_DNS_PLUGIN_GET_CLASS (self)->is_caching (self);
return NM_DNS_PLUGIN_GET_CLASS (self)->is_caching;
}
const char *
nm_dns_plugin_get_name (NMDnsPlugin *self)
{
g_assert (NM_DNS_PLUGIN_GET_CLASS (self)->get_name);
return NM_DNS_PLUGIN_GET_CLASS (self)->get_name (self);
}
NMDnsPluginClass *klass;
/*****************************************************************************/
g_return_val_if_fail (NM_IS_DNS_PLUGIN (self), NULL);
static void
_clear_pidfile (NMDnsPlugin *self)
{
NMDnsPluginPrivate *priv = NM_DNS_PLUGIN_GET_PRIVATE (self);
if (priv->pidfile) {
unlink (priv->pidfile);
g_clear_pointer (&priv->pidfile, g_free);
}
}
static void
kill_existing (const char *progname, const char *pidfile, const char *kill_match)
{
long pid;
gs_free char *contents = NULL;
gs_free char *cmdline_contents = NULL;
guint64 start_time;
char proc_path[256];
gs_free_error GError *error = NULL;
if (!pidfile)
return;
if (!kill_match)
g_return_if_reached ();
if (!g_file_get_contents (pidfile, &contents, NULL, &error)) {
if (g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
return;
goto out;
}
pid = _nm_utils_ascii_str_to_int64 (contents, 10, 2, INT_MAX, -1);
if (pid == -1)
goto out;
start_time = nm_utils_get_start_time_for_pid (pid, NULL, NULL);
if (start_time == 0)
goto out;
nm_sprintf_buf (proc_path, "/proc/%ld/cmdline", pid);
if (!g_file_get_contents (proc_path, &cmdline_contents, NULL, NULL))
goto out;
if (!strstr (cmdline_contents, kill_match))
goto out;
nm_utils_kill_process_sync (pid, start_time, SIGKILL, _NMLOG_DOMAIN,
progname ?: "<dns-process>",
0, 0, 1000);
out:
unlink (pidfile);
}
static void
watch_cb (GPid pid, int status, gpointer user_data)
{
NMDnsPlugin *self = NM_DNS_PLUGIN (user_data);
NMDnsPluginPrivate *priv = NM_DNS_PLUGIN_GET_PRIVATE (self);
priv->pid = 0;
priv->watch_id = 0;
g_clear_pointer (&priv->progname, g_free);
_clear_pidfile (self);
g_signal_emit (self, signals[CHILD_QUIT], 0, status);
}
GPid
nm_dns_plugin_child_pid (NMDnsPlugin *self)
{
NMDnsPluginPrivate *priv;
g_return_val_if_fail (NM_IS_DNS_PLUGIN (self), 0);
priv = NM_DNS_PLUGIN_GET_PRIVATE (self);
return priv->pid;
}
GPid
nm_dns_plugin_child_spawn (NMDnsPlugin *self,
const char **argv,
const char *pidfile,
const char *kill_match)
{
NMDnsPluginPrivate *priv;
GError *error = NULL;
GPid pid;
gs_free char *cmdline = NULL;
gs_free char *progname = NULL;
g_return_val_if_fail (argv && argv[0], 0);
g_return_val_if_fail (NM_IS_DNS_PLUGIN (self), 0);
priv = NM_DNS_PLUGIN_GET_PRIVATE (self);
g_return_val_if_fail (!priv->pid, 0);
nm_assert (!priv->progname);
nm_assert (!priv->watch_id);
nm_assert (!priv->pidfile);
progname = g_path_get_basename (argv[0]);
kill_existing (progname, pidfile, kill_match);
_LOGI ("starting %s...", progname);
_LOGD ("command line: %s",
(cmdline = g_strjoinv (" ", (char **) argv)));
if (!g_spawn_async (NULL, (char **) argv, NULL,
G_SPAWN_DO_NOT_REAP_CHILD,
nm_utils_setpgid, NULL,
&pid,
&error)) {
_LOGW ("failed to spawn %s: %s",
progname, error->message);
g_clear_error (&error);
return 0;
}
_LOGD ("%s started with pid %d", progname, pid);
priv->watch_id = g_child_watch_add (pid, (GChildWatchFunc) watch_cb, self);
priv->pid = pid;
priv->progname = g_steal_pointer (&progname);
priv->pidfile = g_strdup (pidfile);
return pid;
}
gboolean
nm_dns_plugin_child_kill (NMDnsPlugin *self)
{
NMDnsPluginPrivate *priv = NM_DNS_PLUGIN_GET_PRIVATE (self);
nm_clear_g_source (&priv->watch_id);
if (priv->pid) {
nm_utils_kill_child_sync (priv->pid, SIGTERM, _NMLOG_DOMAIN,
priv->progname ?: "<dns-process>", NULL, 1000, 0);
priv->pid = 0;
g_clear_pointer (&priv->progname, g_free);
}
_clear_pidfile (self);
return TRUE;
klass = NM_DNS_PLUGIN_GET_CLASS (self);
nm_assert (klass->plugin_name);
return klass->plugin_name;
}
void
nm_dns_plugin_stop (NMDnsPlugin *self)
{
nm_dns_plugin_child_kill (self);
NMDnsPluginClass *klass;
g_return_if_fail (NM_IS_DNS_PLUGIN (self));
klass = NM_DNS_PLUGIN_GET_CLASS (self);
if (klass->stop)
klass->stop (self);
}
/*****************************************************************************/
......@@ -253,49 +103,9 @@ nm_dns_plugin_stop (NMDnsPlugin *self)
static void
nm_dns_plugin_init (NMDnsPlugin *self)
{
self->_priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NM_TYPE_DNS_PLUGIN, NMDnsPluginPrivate);
}
static void
dispose (GObject *object)
{
NMDnsPlugin *self = NM_DNS_PLUGIN (object);
nm_dns_plugin_stop (self);
G_OBJECT_CLASS (nm_dns_plugin_parent_class)->dispose (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));
object_class->dispose = dispose;
plugin_class->is_caching = is_caching;
/* 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.
*/
signals[FAILED] =
g_signal_new (NM_DNS_PLUGIN_FAILED,
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
0, 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);
}
......@@ -2,8 +2,8 @@
/* Copyright (C) 2010 Red Hat, Inc.
*/
#ifndef __NETWORKMANAGER_DNS_PLUGIN_H__
#define __NETWORKMANAGER_DNS_PLUGIN_H__
#ifndef __NM_DNS_PLUGIN_H__
#define __NM_DNS_PLUGIN_H__
#include "nm-dns-manager.h"
#include "nm-config-data.h"
......@@ -15,21 +15,13 @@
#define NM_IS_DNS_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), 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"
struct _NMDnsPluginPrivate;
typedef struct {
GObject parent;
struct _NMDnsPluginPrivate *_priv;
} NMDnsPlugin;
typedef struct {
GObjectClass parent;
/* Methods */
/* Called when DNS information is changed. 'configs' is an array
* of pointers to NMDnsIPConfigData sorted by priority.
* 'global_config' is the optional global DNS
......@@ -38,25 +30,19 @@ typedef struct {
gboolean (*update) (NMDnsPlugin *self,
const NMGlobalDnsConfig *global_config,
const CList *ip_config_lst_head,
const char *hostname);
const char *hostname,
GError **error);
/* 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_caching) (NMDnsPlugin *self);
/* Subclasses should override this and return their plugin name */
const char *(*get_name) (NMDnsPlugin *self);
void (*stop) (NMDnsPlugin *self);
/* Signals */
const char *plugin_name;
/* 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.
/* Types should set to TRUE if they start a local caching nameserver
* that listens on localhost and would block any other local caching
* nameserver from operating.
*/
void (*child_quit) (NMDnsPlugin *self, int status);
bool is_caching:1;
} NMDnsPluginClass;
GType nm_dns_plugin_get_type (void);
......@@ -68,25 +54,9 @@ const char *nm_dns_plugin_get_name (NMDnsPlugin *self);
gboolean nm_dns_plugin_update (NMDnsPlugin *self,
const NMGlobalDnsConfig *global_config,
const CList *ip_config_lst_head,
const char *hostname);
const char *hostname,
GError **error);
void nm_dns_plugin_stop (NMDnsPlugin *self);
/* 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);
GPid nm_dns_plugin_child_pid (NMDnsPlugin *self);
gboolean nm_dns_plugin_child_kill (NMDnsPlugin *self);
#endif /* __NETWORKMANAGER_DNS_PLUGIN_H__ */
#endif /* __NM_DNS_PLUGIN_H__ */
......@@ -338,7 +338,8 @@ static gboolean
update (NMDnsPlugin *plugin,
const NMGlobalDnsConfig *global_config,
const CList *ip_config_lst_head,
const char *hostname)
const char *hostname,
GError **error)
{
NMDnsSystemdResolved *self = NM_DNS_SYSTEMD_RESOLVED (plugin);
gs_unref_hashtable GHashTable *interfaces = NULL;
......@@ -388,20 +389,6 @@ update (NMDnsPlugin *plugin,
/*****************************************************************************/
static gboolean
is_caching (NMDnsPlugin *plugin)
{
return TRUE;
}
static const char *
get_name (NMDnsPlugin *plugin)
{
return "systemd-resolved";
}
/*****************************************************************************/
static void
name_owner_changed (NMDnsSystemdResolved *self,
const char *owner)
......@@ -553,7 +540,7 @@ nm_dns_systemd_resolved_class_init (NMDnsSystemdResolvedClass *dns_class)
object_class->dispose = dispose;
plugin_class->is_caching = is_caching;
plugin_class->update = update;
plugin_class->get_name = get_name;
plugin_class->plugin_name = "systemd-resolved";
plugin_class->is_caching = TRUE;
plugin_class->update = update;
}
......@@ -27,9 +27,11 @@ static gboolean
update (NMDnsPlugin *plugin,
const NMGlobalDnsConfig *global_config,
const CList *ip_config_lst_head,
const char *hostname)
const char *hostname,
GError **error)
{
char *argv[] = { DNSSEC_TRIGGER_PATH, "--async", "--update", NULL };
gs_free_error GError *local = NULL;
int status;
/* TODO: We currently call a script installed with the dnssec-trigger
......@@ -41,23 +43,21 @@ update (NMDnsPlugin *plugin,
* without calling custom scripts. The dnssec-trigger functionality
* may be eventually merged into NetworkManager.
*/
if (!g_spawn_sync ("/", argv, NULL, 0, NULL, NULL, NULL, NULL, &status, NULL))
if (!g_spawn_sync (