dns: allow runtime selection of resolv.conf manager

Add a new 'rc-manager' configuration parameter that allows to select
the strategy used to write resolv.conf; currently supported values
are: none|resolvconf|netconfig, 'none' meaning that NM directly writes
the file.

The default value of the parameter is 'none'; however if a
RESOLVCONF_PATH (or NETCONFIG_PATH) is specified at build time, the
default value will be 'resolvconf' (or 'netconfig').
This commit is contained in:
Beniamino Galvani
2015-04-20 11:11:32 +02:00
parent de0d623680
commit e573977b80
6 changed files with 111 additions and 21 deletions

View File

@@ -733,10 +733,10 @@ if test "$with_netconfig" = "yes"; then
fi
# Define resolvconf and netconfig paths
if test "$with_resolvconf" != "no"; then
AC_DEFINE_UNQUOTED(RESOLVCONF_PATH, "$with_resolvconf", [Path to resolvconf (if enabled)])
AC_DEFINE_UNQUOTED(RESOLVCONF_PATH, "$with_resolvconf", [Path to resolvconf])
fi
if test "$with_netconfig" != "no"; then
AC_DEFINE_UNQUOTED(NETCONFIG_PATH, "$with_netconfig", [Path to netconfig (if enabled)])
AC_DEFINE_UNQUOTED(NETCONFIG_PATH, "$with_netconfig", [Path to netconfig])
fi
# iptables path

View File

@@ -72,6 +72,18 @@ G_DEFINE_TYPE (NMDnsManager, nm_dns_manager, G_TYPE_OBJECT)
#define HASH_LEN 20
#ifdef RESOLVCONF_PATH
#define RESOLVCONF_SELECTED
#else
#define RESOLVCONF_PATH "/sbin/resolvconf"
#endif
#ifdef NETCONFIG_PATH
#define NETCONFIG_SELECTED
#else
#define NETCONFIG_PATH "/sbin/netconfig"
#endif
typedef struct {
NMIP4Config *ip4_vpn_config;
NMIP4Config *ip4_device_config;
@@ -85,6 +97,7 @@ typedef struct {
guint8 prev_hash[HASH_LEN]; /* Hash when begin_updates() was called */
NMDnsManagerResolvConfMode resolv_conf_mode;
NMDnsManagerResolvConfManager rc_manager;
NMDnsPlugin *plugin;
NMConfig *config;
@@ -223,10 +236,6 @@ merge_one_ip6_config (NMResolvConfData *rc, NMIP6Config *src)
}
#if defined(NETCONFIG_PATH)
/**********************************/
/* SUSE */
static GPid
run_netconfig (GError **error, gint *stdin_fd)
{
@@ -328,8 +337,6 @@ dispatch_netconfig (char **searches,
return ret > 0;
}
#endif
static gboolean
write_resolv_conf (FILE *f,
@@ -390,7 +397,6 @@ write_resolv_conf (FILE *f,
return retval;
}
#ifdef RESOLVCONF_PATH
static gboolean
dispatch_resolvconf (char **searches,
char **nameservers,
@@ -443,7 +449,6 @@ dispatch_resolvconf (char **searches,
return retval;
}
#endif
#define MY_RESOLV_CONF NMRUNDIR "/resolv.conf"
#define MY_RESOLV_CONF_TMP MY_RESOLV_CONF ".tmp"
@@ -826,18 +831,26 @@ update_dns (NMDnsManager *self,
}
if (update) {
#if defined(RESOLVCONF_PATH)
success = dispatch_resolvconf (searches, nameservers, error);
#elif defined(NETCONFIG_PATH)
success = dispatch_netconfig (searches, nameservers, nis_domain,
nis_servers, error);
#else
success = update_resolv_conf (searches, nameservers, error, TRUE);
#endif
switch (priv->rc_manager) {
case NM_DNS_MANAGER_RESOLV_CONF_MAN_NONE:
success = update_resolv_conf (searches, nameservers, error, TRUE);
break;
case NM_DNS_MANAGER_RESOLV_CONF_MAN_RESOLVCONF:
success = dispatch_resolvconf (searches, nameservers, error);
break;
case NM_DNS_MANAGER_RESOLV_CONF_MAN_NETCONFIG:
success = dispatch_netconfig (searches, nameservers, nis_domain,
nis_servers, error);
break;
default:
g_assert_not_reached ();
}
}
/* Only update private resolv.conf in NMRUNDIR, ignore errors */
update_resolv_conf (searches, nameservers, error, FALSE);
/* Unless we've already done it, update private resolv.conf in NMRUNDIR
ignoring any errors */
if (!(update && priv->rc_manager == NM_DNS_MANAGER_RESOLV_CONF_MAN_NONE))
update_resolv_conf (searches, nameservers, error, FALSE);
/* signal that resolv.conf was changed */
if (update && success)
@@ -1175,6 +1188,46 @@ init_resolv_conf_mode (NMDnsManager *self)
}
}
static void
init_resolv_conf_manager (NMDnsManager *self)
{
NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self);
const char *man, *desc = "";
man = nm_config_data_get_rc_manager (nm_config_get_data (priv->config));
if (!g_strcmp0 (man, "none"))
priv->rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_NONE;
else if (!g_strcmp0 (man, "resolvconf"))
priv->rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_RESOLVCONF;
else if (!g_strcmp0 (man, "netconfig"))
priv->rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_NETCONFIG;
else {
#if defined(RESOLVCONF_SELECTED)
priv->rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_RESOLVCONF;
#elif defined(NETCONFIG_SELECTED)
priv->rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_NETCONFIG;
#else
priv->rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_NONE;
#endif
if (man)
nm_log_warn (LOGD_DNS, "DNS: unknown resolv.conf manager '%s'", man);
}
switch (priv->rc_manager) {
case NM_DNS_MANAGER_RESOLV_CONF_MAN_RESOLVCONF:
desc = "resolvconf";
break;
case NM_DNS_MANAGER_RESOLV_CONF_MAN_NETCONFIG:
desc = "netconfig";
break;
case NM_DNS_MANAGER_RESOLV_CONF_MAN_NONE:
desc = "none";
break;
}
nm_log_info (LOGD_DNS, "DNS: using resolv.conf manager '%s'", desc);
}
static void
config_changed_cb (NMConfig *config,
NMConfigData *config_data,
@@ -1184,10 +1237,12 @@ config_changed_cb (NMConfig *config,
{
GError *error = NULL;
if (!(changes & NM_CONFIG_CHANGE_DNS_MODE))
if (!NM_FLAGS_ANY (changes, NM_CONFIG_CHANGE_DNS_MODE |
NM_CONFIG_CHANGE_RC_MANAGER))
return;
init_resolv_conf_mode (self);
init_resolv_conf_manager (self);
if (!update_dns (self, TRUE, &error)) {
nm_log_warn (LOGD_DNS, "could not commit DNS changes: %s", error->message);
g_clear_error (&error);
@@ -1208,6 +1263,7 @@ nm_dns_manager_init (NMDnsManager *self)
G_CALLBACK (config_changed_cb),
self);
init_resolv_conf_mode (self);
init_resolv_conf_manager (self);
}
static void

View File

@@ -99,6 +99,22 @@ typedef enum {
NM_DNS_MANAGER_RESOLV_CONF_PROXY
} NMDnsManagerResolvConfMode;
/**
* NMDnsManagerResolvConfManager
* @NM_DNS_MANAGER_RESOLV_CONF_MAN_NONE: NM directly writes resolv.conf
* @NM_DNS_MANAGER_RESOLV_CONF_MAN_RESOLVCONF: NM is managing resolv.conf
through resolvconf
* @NM_DNS_MANAGER_RESOLV_CONF_MAN_NETCONFIG: NM is managing resolv.conf
through netconfig
*
* NMDnsManager's management of resolv.conf
*/
typedef enum {
NM_DNS_MANAGER_RESOLV_CONF_MAN_NONE,
NM_DNS_MANAGER_RESOLV_CONF_MAN_RESOLVCONF,
NM_DNS_MANAGER_RESOLV_CONF_MAN_NETCONFIG,
} NMDnsManagerResolvConfManager;
NMDnsManagerResolvConfMode nm_dns_manager_get_resolv_conf_mode (NMDnsManager *mgr);
G_END_DECLS

View File

@@ -44,6 +44,7 @@ typedef struct {
} no_auto_default;
char *dns_mode;
char *rc_manager;
} NMConfigDataPrivate;
@@ -138,6 +139,14 @@ nm_config_data_get_dns_mode (const NMConfigData *self)
return NM_CONFIG_DATA_GET_PRIVATE (self)->dns_mode;
}
const char *
nm_config_data_get_rc_manager (const NMConfigData *self)
{
g_return_val_if_fail (self, NULL);
return NM_CONFIG_DATA_GET_PRIVATE (self)->rc_manager;
}
/************************************************************************/
static gboolean
@@ -205,6 +214,9 @@ nm_config_data_diff (NMConfigData *old_data, NMConfigData *new_data)
if (g_strcmp0 (nm_config_data_get_dns_mode (old_data), nm_config_data_get_dns_mode (new_data)))
changes |= NM_CONFIG_CHANGE_DNS_MODE;
if (g_strcmp0 (nm_config_data_get_rc_manager (old_data), nm_config_data_get_rc_manager (new_data)))
changes |= NM_CONFIG_CHANGE_RC_MANAGER;
return changes;
}
@@ -300,6 +312,7 @@ finalize (GObject *gobject)
g_strfreev (priv->no_auto_default.arr);
g_free (priv->dns_mode);
g_free (priv->rc_manager);
g_key_file_unref (priv->keyfile);
@@ -325,6 +338,7 @@ constructed (GObject *object)
priv->connectivity.interval = MAX (0, interval);
priv->dns_mode = g_key_file_get_value (priv->keyfile, "main", "dns", NULL);
priv->rc_manager = g_key_file_get_value (priv->keyfile, "main", "rc-manager", NULL);
G_OBJECT_CLASS (nm_config_data_parent_class)->constructed (object);
}

View File

@@ -52,6 +52,7 @@ typedef enum { /*< flags >*/
NM_CONFIG_CHANGE_CONNECTIVITY = (1L << 2),
NM_CONFIG_CHANGE_NO_AUTO_DEFAULT = (1L << 3),
NM_CONFIG_CHANGE_DNS_MODE = (1L << 4),
NM_CONFIG_CHANGE_RC_MANAGER = (1L << 5),
_NM_CONFIG_CHANGE_LAST,
NM_CONFIG_CHANGE_ALL = ((_NM_CONFIG_CHANGE_LAST - 1) << 1) - 1,
@@ -88,6 +89,7 @@ const char *const*nm_config_data_get_no_auto_default (const NMConfigData *config
const GSList * nm_config_data_get_no_auto_default_list (const NMConfigData *config_data);
const char *nm_config_data_get_dns_mode (const NMConfigData *self);
const char *nm_config_data_get_rc_manager (const NMConfigData *self);
G_END_DECLS

View File

@@ -738,6 +738,8 @@ _change_flags_one_to_string (NMConfigChangeFlags flag)
return "no-auto-default";
case NM_CONFIG_CHANGE_DNS_MODE:
return "dns-mode";
case NM_CONFIG_CHANGE_RC_MANAGER:
return "rc-manager";
default:
g_return_val_if_reached ("unknown");
}