dns: allow runtime selection of resolv.conf manager
authorBeniamino Galvani <bgalvani@redhat.com>
Mon, 20 Apr 2015 09:11:32 +0000 (11:11 +0200)
committerBeniamino Galvani <bgalvani@redhat.com>
Mon, 4 May 2015 07:42:25 +0000 (09:42 +0200)
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').

configure.ac
src/dns-manager/nm-dns-manager.c
src/dns-manager/nm-dns-manager.h
src/nm-config-data.c
src/nm-config-data.h
src/nm-config.c

index 436db10..0689fd5 100644 (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
index 1b75c91..2e5fa81 100644 (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
index bc374fc..a3e6cb2 100644 (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
index 45d90b5..a987a8f 100644 (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);
 }
index f260a73..50c5399 100644 (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
 
index 3dbe58f..8e8100f 100644 (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");
        }