mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-05-15 18:18:06 +02:00
Now all the plugins for configuration of DNS resolvers have their own implementation of checksums. This is required, because the plugins are paying different amount of attention to different parameters of connections. The previous common implementation for example ignored new routes and thus did not trigger sending update with forwarding of reverse DNS queries to those servers. Additionally to make dns-manager more clear, operations with resolv.conf have been moved to their separate plugin nm-dns-resolv_conf
256 lines
8.9 KiB
C
256 lines
8.9 KiB
C
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
/*
|
|
* Copyright (C) 2010 - 2012 Red Hat, Inc.
|
|
*/
|
|
|
|
#include "src/core/nm-default-daemon.h"
|
|
|
|
#include "nm-dns-plugin.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <sys/types.h>
|
|
#include <sys/wait.h>
|
|
|
|
#include "libnm-core-intern/nm-core-internal.h"
|
|
#include "NetworkManagerUtils.h"
|
|
|
|
/*****************************************************************************/
|
|
|
|
enum {
|
|
UPDATE_PENDING_CHANGED,
|
|
LAST_SIGNAL,
|
|
};
|
|
|
|
static guint signals[LAST_SIGNAL] = {0};
|
|
|
|
typedef struct _NMDnsPluginPrivate {
|
|
bool update_pending_inited : 1;
|
|
bool update_pending : 1;
|
|
} NMDnsPluginPrivate;
|
|
|
|
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)
|
|
|
|
/*****************************************************************************/
|
|
|
|
#define _NMLOG_PREFIX_NAME "dns-plugin"
|
|
#define _NMLOG_DOMAIN LOGD_DNS
|
|
#define _NMLOG(level, ...) \
|
|
G_STMT_START \
|
|
{ \
|
|
const NMLogLevel __level = (level); \
|
|
\
|
|
if (nm_logging_enabled(__level, _NMLOG_DOMAIN)) { \
|
|
char __prefix[20]; \
|
|
const NMDnsPlugin *const __self = (self); \
|
|
\
|
|
_nm_log(__level, \
|
|
_NMLOG_DOMAIN, \
|
|
0, \
|
|
NULL, \
|
|
NULL, \
|
|
"%s%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \
|
|
_NMLOG_PREFIX_NAME, \
|
|
(!__self ? "" \
|
|
: nm_sprintf_buf(__prefix, \
|
|
"[" NM_HASH_OBFUSCATE_PTR_FMT "]", \
|
|
NM_HASH_OBFUSCATE_PTR( \
|
|
__self))) _NM_UTILS_MACRO_REST(__VA_ARGS__)); \
|
|
} \
|
|
} \
|
|
G_STMT_END
|
|
|
|
NM_UTILS_LOOKUP_STR_DEFINE(
|
|
_rc_manager_to_string,
|
|
NMDnsManagerResolvConfManager,
|
|
NM_UTILS_LOOKUP_DEFAULT_WARN(NULL),
|
|
NM_UTILS_LOOKUP_STR_ITEM(NM_DNS_MANAGER_RESOLV_CONF_MAN_AUTO, "auto"),
|
|
NM_UTILS_LOOKUP_STR_ITEM(NM_DNS_MANAGER_RESOLV_CONF_MAN_UNKNOWN, "unknown"),
|
|
NM_UTILS_LOOKUP_STR_ITEM(NM_DNS_MANAGER_RESOLV_CONF_MAN_UNMANAGED, "unmanaged"),
|
|
NM_UTILS_LOOKUP_STR_ITEM(NM_DNS_MANAGER_RESOLV_CONF_MAN_IMMUTABLE, "immutable"),
|
|
NM_UTILS_LOOKUP_STR_ITEM(NM_DNS_MANAGER_RESOLV_CONF_MAN_SYMLINK, "symlink"),
|
|
NM_UTILS_LOOKUP_STR_ITEM(NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE, "file"),
|
|
NM_UTILS_LOOKUP_STR_ITEM(NM_DNS_MANAGER_RESOLV_CONF_MAN_RESOLVCONF, "resolvconf"),
|
|
NM_UTILS_LOOKUP_STR_ITEM(NM_DNS_MANAGER_RESOLV_CONF_MAN_NETCONFIG, "netconfig"), );
|
|
|
|
/*****************************************************************************/
|
|
|
|
gboolean
|
|
nm_dns_plugin_update(NMDnsPlugin *self, NMDnsUpdateData *update_data, 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, update_data, error);
|
|
}
|
|
|
|
void
|
|
nm_dns_plugin_checksum(NMDnsPlugin *self,
|
|
const NML3ConfigData *l3cd,
|
|
GChecksum *sum,
|
|
int addr_family,
|
|
NMDnsIPConfigType dns_ip_config_type)
|
|
{
|
|
NM_DNS_PLUGIN_GET_CLASS(self)->checksum(l3cd, sum, addr_family, dns_ip_config_type);
|
|
}
|
|
|
|
gboolean
|
|
nm_dns_plugin_is_caching(NMDnsPlugin *self)
|
|
{
|
|
return NM_DNS_PLUGIN_GET_CLASS(self)->is_caching;
|
|
}
|
|
|
|
const char *
|
|
nm_dns_plugin_get_name(NMDnsPlugin *self)
|
|
{
|
|
NMDnsPluginClass *klass;
|
|
|
|
g_return_val_if_fail(NM_IS_DNS_PLUGIN(self), NULL);
|
|
|
|
klass = NM_DNS_PLUGIN_GET_CLASS(self);
|
|
nm_assert(klass->plugin_name);
|
|
return klass->plugin_name;
|
|
}
|
|
|
|
const guint8 *
|
|
nm_dns_plugin_get_hash(NMDnsPlugin *self)
|
|
{
|
|
NMDnsPluginClass *klass;
|
|
|
|
g_return_val_if_fail(NM_IS_DNS_PLUGIN(self), NULL);
|
|
|
|
klass = NM_DNS_PLUGIN_GET_CLASS(self);
|
|
|
|
return klass->hash;
|
|
}
|
|
|
|
void
|
|
nm_dns_plugin_set_hash(NMDnsPlugin *self, guint8 *hash)
|
|
{
|
|
NMDnsPluginClass *klass;
|
|
|
|
klass = NM_DNS_PLUGIN_GET_CLASS(self);
|
|
memcpy(klass->hash, hash, NM_UTILS_CHECKSUM_LENGTH_SHA1);
|
|
}
|
|
|
|
void
|
|
nm_dns_plugin_stop(NMDnsPlugin *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);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
static gboolean
|
|
_get_update_pending(NMDnsPlugin *self)
|
|
{
|
|
NMDnsPluginClass *klass;
|
|
|
|
nm_assert(NM_IS_DNS_PLUGIN(self));
|
|
|
|
klass = NM_DNS_PLUGIN_GET_CLASS(self);
|
|
if (klass->get_update_pending) {
|
|
if (klass->get_update_pending(self))
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
gboolean
|
|
nm_dns_plugin_get_update_pending(NMDnsPlugin *self)
|
|
{
|
|
NMDnsPluginPrivate *priv;
|
|
|
|
g_return_val_if_fail(NM_IS_DNS_PLUGIN(self), FALSE);
|
|
|
|
priv = NM_DNS_PLUGIN_GET_PRIVATE(self);
|
|
|
|
/* We cache the boolean and rely on the subclass to call
|
|
* _nm_dns_plugin_update_pending_maybe_changed(). The subclass
|
|
* anyway must get it right to notify us when the value (maybe)
|
|
* changes. By caching the value, the subclass is free to notify
|
|
* even if the value did not actually change.
|
|
*
|
|
* Also, this allows the base implementation to combine multiple
|
|
* sources/reasons (if we need that in the future). */
|
|
|
|
if (!priv->update_pending_inited) {
|
|
priv->update_pending_inited = TRUE;
|
|
priv->update_pending = _get_update_pending(self);
|
|
_LOGD("[%s] update-pending changed (%spending)",
|
|
nm_dns_plugin_get_name(self),
|
|
priv->update_pending ? "" : "not ");
|
|
} else
|
|
nm_assert(priv->update_pending == _get_update_pending(self));
|
|
|
|
return priv->update_pending;
|
|
}
|
|
|
|
void
|
|
_nm_dns_plugin_update_pending_maybe_changed(NMDnsPlugin *self)
|
|
{
|
|
NMDnsPluginPrivate *priv;
|
|
gboolean v;
|
|
|
|
g_return_if_fail(NM_IS_DNS_PLUGIN(self));
|
|
|
|
priv = NM_DNS_PLUGIN_GET_PRIVATE(self);
|
|
|
|
v = _get_update_pending(self);
|
|
|
|
if (!priv->update_pending_inited)
|
|
priv->update_pending_inited = TRUE;
|
|
else if (priv->update_pending == v)
|
|
return;
|
|
|
|
priv->update_pending = v;
|
|
|
|
_LOGD("[%s] update-pending changed (%spending)",
|
|
nm_dns_plugin_get_name(self),
|
|
priv->update_pending ? "" : "not ");
|
|
|
|
g_signal_emit(self, signals[UPDATE_PENDING_CHANGED], 0, (gboolean) priv->update_pending);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
static void
|
|
nm_dns_plugin_init(NMDnsPlugin *self)
|
|
{
|
|
NMDnsPluginPrivate *priv;
|
|
|
|
priv = G_TYPE_INSTANCE_GET_PRIVATE(self, NM_TYPE_DNS_PLUGIN, NMDnsPluginPrivate);
|
|
|
|
self->_priv = priv;
|
|
|
|
nm_assert(priv->update_pending_inited == FALSE);
|
|
nm_assert(priv->update_pending == FALSE);
|
|
|
|
nm_shutdown_wait_obj_register_object(self, "dns-plugin");
|
|
}
|
|
|
|
static void
|
|
nm_dns_plugin_class_init(NMDnsPluginClass *klass)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS(klass);
|
|
|
|
g_type_class_add_private(object_class, sizeof(NMDnsPluginPrivate));
|
|
|
|
signals[UPDATE_PENDING_CHANGED] = g_signal_new(NM_DNS_PLUGIN_UPDATE_PENDING_CHANGED,
|
|
G_OBJECT_CLASS_TYPE(klass),
|
|
G_SIGNAL_RUN_FIRST,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
G_TYPE_NONE,
|
|
1,
|
|
G_TYPE_BOOLEAN);
|
|
}
|