summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBeniamino Galvani <bgalvani@redhat.com>2015-05-04 09:47:15 +0200
committerBeniamino Galvani <bgalvani@redhat.com>2015-05-04 09:47:15 +0200
commitad6dbc504badb0c91c5f8da7b043ae892fb19fe8 (patch)
treedc655f86b64f5e6ce06780a1354302c3e40e0f3a
parentf529fedd178515bf3529ba1e758fc3f6e217b708 (diff)
parentb1a81e5165e21eec82a68a3aece24027d58f5330 (diff)
downloadNetworkManager-ad6dbc504badb0c91c5f8da7b043ae892fb19fe8.tar.gz
dns: merge branch 'bg/resolv-conf-bgo747821'
https://bugzilla.gnome.org/show_bug.cgi?id=747821
-rw-r--r--configure.ac4
-rw-r--r--man/NetworkManager.conf.xml.in14
-rw-r--r--src/dns-manager/nm-dns-manager.c141
-rw-r--r--src/dns-manager/nm-dns-manager.h16
-rw-r--r--src/nm-config-data.c14
-rw-r--r--src/nm-config-data.h2
-rw-r--r--src/nm-config.c2
7 files changed, 160 insertions, 33 deletions
diff --git a/configure.ac b/configure.ac
index 436db10cc7..0689fd526a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -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
diff --git a/man/NetworkManager.conf.xml.in b/man/NetworkManager.conf.xml.in
index ae4ba88fd6..7807b1bf9d 100644
--- a/man/NetworkManager.conf.xml.in
+++ b/man/NetworkManager.conf.xml.in
@@ -254,6 +254,20 @@ no-auto-default=*
</varlistentry>
<varlistentry>
+ <term><varname>rc-manager</varname></term>
+ <listitem><para>Set the <filename>resolv.conf</filename>
+ management mode. The default value depends on how NetworkManager
+ was built.</para>
+ <para><literal>none</literal>: NetworkManager will directly
+ write changes to <filename>resolv.conf</filename>.</para>
+ <para><literal>resolvconf</literal>: NetworkManager will run
+ resolvconf to update the DNS configuration.</para>
+ <para><literal>netconfig</literal>: NetworkManager will run
+ netconfig to update the DNS configuration.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><varname>debug</varname></term>
<listitem><para>Comma separated list of options to aid
debugging. This value will be combined with the environment
diff --git a/src/dns-manager/nm-dns-manager.c b/src/dns-manager/nm-dns-manager.c
index 490a4cd1db..2e5fa814b3 100644
--- a/src/dns-manager/nm-dns-manager.c
+++ b/src/dns-manager/nm-dns-manager.c
@@ -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"
@@ -452,13 +457,32 @@ dispatch_resolvconf (char **searches,
static gboolean
update_resolv_conf (char **searches,
char **nameservers,
- GError **error)
+ GError **error,
+ gboolean install_etc)
{
FILE *f;
struct stat st;
g_return_val_if_fail (error != NULL, FALSE);
+ /* If we are not managing /etc/resolv.conf and it points to
+ * MY_RESOLV_CONF, don't write the private DNS configuration to
+ * MY_RESOLV_CONF otherwise we would overwrite the changes done by
+ * some external application.
+ */
+ if (!install_etc) {
+ char *path = g_file_read_link (_PATH_RESCONF, NULL);
+ gboolean ours = !g_strcmp0 (path, MY_RESOLV_CONF);
+
+ g_free (path);
+
+ if (ours) {
+ nm_log_dbg (LOGD_DNS, "not updating " MY_RESOLV_CONF
+ " since it points to " _PATH_RESCONF);
+ return FALSE;
+ }
+ }
+
if ((f = fopen (MY_RESOLV_CONF_TMP, "w")) == NULL) {
g_set_error (error,
NM_MANAGER_ERROR,
@@ -498,6 +522,9 @@ update_resolv_conf (char **searches,
return FALSE;
}
+ if (!install_etc)
+ return TRUE;
+
/* Don't overwrite a symbolic link unless it points to MY_RESOLV_CONF. */
if (lstat (_PATH_RESCONF, &st) != -1) {
/* Don't overwrite a symbolic link. */
@@ -654,18 +681,19 @@ update_dns (NMDnsManager *self,
char **nameservers = NULL;
char **nis_servers = NULL;
int num, i, len;
- gboolean success = FALSE, caching = FALSE;
+ gboolean success = FALSE, caching = FALSE, update = TRUE;
g_return_val_if_fail (!error || !*error, FALSE);
priv = NM_DNS_MANAGER_GET_PRIVATE (self);
- if (priv->resolv_conf_mode == NM_DNS_MANAGER_RESOLV_CONF_UNMANAGED)
- return TRUE;
-
- priv->dns_touched = TRUE;
-
- nm_log_dbg (LOGD_DNS, "updating resolv.conf");
+ if (priv->resolv_conf_mode == NM_DNS_MANAGER_RESOLV_CONF_UNMANAGED) {
+ update = FALSE;
+ nm_log_dbg (LOGD_DNS, "not updating resolv.conf");
+ } else {
+ priv->dns_touched = TRUE;
+ nm_log_dbg (LOGD_DNS, "updating resolv.conf");
+ }
/* Update hash with config we're applying */
compute_hash (self, priv->hash);
@@ -754,7 +782,7 @@ update_dns (NMDnsManager *self,
nis_domain = rc.nis_domain;
/* Let any plugins do their thing first */
- if (priv->plugin) {
+ if (update && priv->plugin) {
NMDnsPlugin *plugin = priv->plugin;
const char *plugin_name = nm_dns_plugin_get_name (plugin);
GSList *vpn_configs = NULL, *dev_configs = NULL, *other_configs = NULL;
@@ -802,22 +830,30 @@ update_dns (NMDnsManager *self,
nameservers[0] = g_strdup ("127.0.0.1");
}
-#ifdef RESOLVCONF_PATH
- success = dispatch_resolvconf (searches, nameservers, error);
-#endif
-
-#ifdef NETCONFIG_PATH
- if (success == FALSE) {
- success = dispatch_netconfig (searches, nameservers,
- nis_domain, nis_servers, error);
+ if (update) {
+ 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 ();
+ }
}
-#endif
- if (success == FALSE)
- success = update_resolv_conf (searches, nameservers, error);
+ /* 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 (success)
+ if (update && success)
g_signal_emit (self, signals[CONFIG_CHANGED], 0);
if (searches)
@@ -827,7 +863,7 @@ update_dns (NMDnsManager *self,
if (nis_servers)
g_strfreev (nis_servers);
- return success;
+ return !update || success;
}
static void
@@ -1153,6 +1189,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,
NMConfigChangeFlags changes,
@@ -1161,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);
@@ -1185,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
diff --git a/src/dns-manager/nm-dns-manager.h b/src/dns-manager/nm-dns-manager.h
index bc374fcf5f..a3e6cb2699 100644
--- a/src/dns-manager/nm-dns-manager.h
+++ b/src/dns-manager/nm-dns-manager.h
@@ -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
diff --git a/src/nm-config-data.c b/src/nm-config-data.c
index 45d90b51d2..a987a8f3ef 100644
--- a/src/nm-config-data.c
+++ b/src/nm-config-data.c
@@ -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);
}
diff --git a/src/nm-config-data.h b/src/nm-config-data.h
index f260a73a90..50c53995ad 100644
--- a/src/nm-config-data.h
+++ b/src/nm-config-data.h
@@ -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
diff --git a/src/nm-config.c b/src/nm-config.c
index 3dbe58fb90..8e8100fe89 100644
--- a/src/nm-config.c
+++ b/src/nm-config.c
@@ -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");
}