mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-04-21 18:10:54 +02:00
dns: merge branch 'th/dnsmasq-rework'
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/merge_requests/254
This commit is contained in:
commit
35c83138ce
14 changed files with 1036 additions and 566 deletions
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -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.
|
||||
void (*stop) (NMDnsPlugin *self);
|
||||
|
||||
const char *plugin_name;
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
gboolean (*is_caching) (NMDnsPlugin *self);
|
||||
bool is_caching:1;
|
||||
|
||||
/* Subclasses should override this and return their plugin name */
|
||||
const char *(*get_name) (NMDnsPlugin *self);
|
||||
|
||||
/* Signals */
|
||||
|
||||
/* 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, int status);
|
||||
} 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 ("/", argv, NULL, 0, NULL, NULL, NULL, NULL, &status, &local)) {
|
||||
nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN,
|
||||
"error spawning dns-trigger: %s",
|
||||
local->message);
|
||||
return FALSE;
|
||||
return (status == 0);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_caching (NMDnsPlugin *plugin)
|
||||
{
|
||||
}
|
||||
if (status != 0) {
|
||||
nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN,
|
||||
"dns-trigger exited with error code %d",
|
||||
status);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static const char *
|
||||
get_name (NMDnsPlugin *plugin)
|
||||
{
|
||||
return "unbound";
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
|
|
@ -76,7 +76,7 @@ nm_dns_unbound_class_init (NMDnsUnboundClass *klass)
|
|||
{
|
||||
NMDnsPluginClass *plugin_class = NM_DNS_PLUGIN_CLASS (klass);
|
||||
|
||||
plugin_class->update = update;
|
||||
plugin_class->is_caching = is_caching;
|
||||
plugin_class->get_name = get_name;
|
||||
plugin_class->plugin_name = "unbound";
|
||||
plugin_class->is_caching = TRUE;
|
||||
plugin_class->update = update;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1100,7 +1100,7 @@ const char *const NM_PATHS_DEFAULT[] = {
|
|||
};
|
||||
|
||||
const char *
|
||||
nm_utils_find_helper(const char *progname, const char *try_first, GError **error)
|
||||
nm_utils_find_helper (const char *progname, const char *try_first, GError **error)
|
||||
{
|
||||
return nm_utils_file_search_in_paths (progname, try_first, NM_PATHS_DEFAULT, G_FILE_TEST_IS_EXECUTABLE, NULL, NULL, error);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue