diff --git a/man/nm-initrd-generator.xml b/man/nm-initrd-generator.xml
index 170cb883e3..2d3d875532 100644
--- a/man/nm-initrd-generator.xml
+++ b/man/nm-initrd-generator.xml
@@ -158,6 +158,8 @@
+
+
@@ -228,9 +230,13 @@
NetworkManager supports the
- ={CS0|CS4|CS6}
- kernel command line option to set a specific DSCP (TOS) value
- in the IP header of DHCP messages.
+ =VALUE
+ kernel command line option to configure the DNS processing
+ mode. See the description of the "dns" key in
+ the "main section" paragraph of NetworkManager.conf5. For
+ example: rd.net.dns-backend=systemd-resolved,
+ rd.net.dns-backend=dnsconfd
@@ -247,6 +253,17 @@
example: rd.net.dns=2001:db8::1,
rd.net.dns=dns+tls://192.0.2.0,
rd.net.dns=dns+tls://[2001:db8::2]:5353#example.org.
+ In addition, it supports configuring the "resolve-mode"
+ key in the global DNS configuration via the
+ command line option.
+
+
+
+
+ NetworkManager supports the
+ ={CS0|CS4|CS6}
+ kernel command line option to set a specific DSCP (TOS) value
+ in the IP header of DHCP messages.
diff --git a/src/nm-initrd-generator/nm-initrd-generator.c b/src/nm-initrd-generator/nm-initrd-generator.c
index 14a168341e..b89b4e413f 100644
--- a/src/nm-initrd-generator/nm-initrd-generator.c
+++ b/src/nm-initrd-generator/nm-initrd-generator.c
@@ -11,6 +11,7 @@
#include "libnm-core-intern/nm-core-internal.h"
#include "libnm-core-intern/nm-keyfile-internal.h"
#include "libnm-glib-aux/nm-io-utils.h"
+#include "libnm-glib-aux/nm-keyfile-aux.h"
#include "libnm-log-core/nm-logging.h"
/*****************************************************************************/
@@ -155,6 +156,8 @@ main(int argc, char *argv[])
gs_unref_array GArray *confs = NULL;
guint i;
gs_strfreev char **global_dns_servers = NULL;
+ gs_free char *dns_backend = NULL;
+ gs_free char *dns_resolve_mode = NULL;
option_context = g_option_context_new(
"-- [ip=...] [rd.route=...] [bridge=...] [bond=...] [team=...] [vlan=...] "
@@ -195,7 +198,9 @@ main(int argc, char *argv[])
(const char *const *) remaining,
&hostname,
&carrier_timeout_sec,
- &global_dns_servers);
+ &global_dns_servers,
+ &dns_backend,
+ &dns_resolve_mode);
confs = g_array_new(FALSE, FALSE, sizeof(NMUtilsNamedValue));
g_array_set_clear_func(confs, (GDestroyNotify) nm_utils_named_value_clear_with_g_free);
@@ -235,27 +240,32 @@ main(int argc, char *argv[])
g_array_append_val(confs, v);
}
- if (global_dns_servers) {
+ if (global_dns_servers || dns_resolve_mode) {
nm_auto_unref_keyfile GKeyFile *keyfile = NULL;
NMUtilsNamedValue v;
- gs_free char *value = NULL;
-
- value = g_strjoinv(",", global_dns_servers);
+ gs_free char *dns_list = NULL;
keyfile = g_key_file_new();
g_key_file_set_list_separator(keyfile, NM_CONFIG_KEYFILE_LIST_SEPARATOR);
+ nm_key_file_add_group(keyfile, NM_CONFIG_KEYFILE_GROUP_GLOBAL_DNS);
- g_key_file_set_value(keyfile,
- NM_CONFIG_KEYFILE_GROUP_GLOBAL_DNS,
- NM_CONFIG_KEYFILE_KEY_GLOBAL_DNS_OPTIONS,
- "");
- g_key_file_set_value(keyfile,
- NM_CONFIG_KEYFILE_GROUPPREFIX_GLOBAL_DNS_DOMAIN "*",
- NM_CONFIG_KEYFILE_KEY_GLOBAL_DNS_DOMAIN_SERVERS,
- value);
+ if (dns_resolve_mode) {
+ g_key_file_set_value(keyfile,
+ NM_CONFIG_KEYFILE_GROUP_GLOBAL_DNS,
+ NM_CONFIG_KEYFILE_KEY_GLOBAL_DNS_RESOLVE_MODE,
+ dns_resolve_mode);
+ }
+
+ if (global_dns_servers) {
+ dns_list = g_strjoinv(",", global_dns_servers);
+ g_key_file_set_value(keyfile,
+ NM_CONFIG_KEYFILE_GROUPPREFIX_GLOBAL_DNS_DOMAIN "*",
+ NM_CONFIG_KEYFILE_KEY_GLOBAL_DNS_DOMAIN_SERVERS,
+ dns_list);
+ }
if (!dump_to_stdout) {
- add_keyfile_comment(keyfile, "from \"rd.net.dns\"");
+ add_keyfile_comment(keyfile, "from \"rd.net.dns\" and \"rd.net.dns-resolv-mode\"");
}
v = (NMUtilsNamedValue) {
@@ -265,6 +275,26 @@ main(int argc, char *argv[])
g_array_append_val(confs, v);
}
+ if (dns_backend) {
+ nm_auto_unref_keyfile GKeyFile *keyfile = NULL;
+ NMUtilsNamedValue v;
+
+ keyfile = g_key_file_new();
+ g_key_file_set_value(keyfile,
+ NM_CONFIG_KEYFILE_GROUP_MAIN,
+ NM_CONFIG_KEYFILE_KEY_MAIN_DNS,
+ dns_backend);
+ if (!dump_to_stdout) {
+ add_keyfile_comment(keyfile, "from \"rd.net.dns-backend\"");
+ }
+
+ v = (NMUtilsNamedValue) {
+ .name = g_strdup_printf("%s/16-dns-backend.conf", run_config_dir),
+ .value_str = g_key_file_to_data(keyfile, NULL, NULL),
+ };
+ g_array_append_val(confs, v);
+ }
+
if (dump_to_stdout) {
nm_clear_g_free(&connections_dir);
nm_clear_g_free(&initrd_dir);
diff --git a/src/nm-initrd-generator/nm-initrd-generator.h b/src/nm-initrd-generator/nm-initrd-generator.h
index 23dd484889..c2baad4e55 100644
--- a/src/nm-initrd-generator/nm-initrd-generator.h
+++ b/src/nm-initrd-generator/nm-initrd-generator.h
@@ -46,6 +46,8 @@ GHashTable *nmi_cmdline_reader_parse(const char *etc_connections_dir,
const char *const *argv,
char **hostname,
gint64 *carrier_timeout_sec,
- char ***global_dns_servers);
+ char ***global_dns_servers,
+ char **dns_backend,
+ char **dns_resolve_mode);
#endif /* __NM_INITRD_GENERATOR_H__ */
diff --git a/src/nm-initrd-generator/nmi-cmdline-reader.c b/src/nm-initrd-generator/nmi-cmdline-reader.c
index 91fe5d1d51..d6dc1fcb7c 100644
--- a/src/nm-initrd-generator/nmi-cmdline-reader.c
+++ b/src/nm-initrd-generator/nmi-cmdline-reader.c
@@ -34,13 +34,15 @@ typedef struct {
NMConnection *default_connection; /* connection not bound to any ifname */
char *hostname;
GHashTable *znet_ifnames;
+ GPtrArray *global_dns;
+ char *dns_backend;
+ char *dns_resolve_mode;
/* Parameters to be set for all connections */
- gboolean ignore_auto_dns;
- int dhcp_timeout;
- char *dhcp4_vci;
- char *dhcp_dscp;
- GPtrArray *global_dns;
+ gboolean ignore_auto_dns;
+ int dhcp_timeout;
+ char *dhcp4_vci;
+ char *dhcp_dscp;
gint64 carrier_timeout_sec;
} Reader;
@@ -77,6 +79,8 @@ reader_destroy(Reader *reader, gboolean free_hash)
g_hash_table_unref(reader->znet_ifnames);
nm_clear_g_free(&reader->dhcp4_vci);
nm_clear_g_free(&reader->dhcp_dscp);
+ nm_clear_g_free(&reader->dns_backend);
+ nm_clear_g_free(&reader->dns_resolve_mode);
nm_g_slice_free(reader);
if (!free_hash)
return g_steal_pointer(&hash);
@@ -1236,6 +1240,28 @@ reader_parse_global_dns(Reader *reader, char *argument)
g_ptr_array_add(reader->global_dns, g_strdup(argument));
}
+static void
+reader_parse_dns_backend(Reader *reader, const char *argument)
+{
+ if (!NM_IN_STRSET(argument, "none", "default", "systemd-resolved", "dnsmasq", "dnsconfd")) {
+ _LOGW(LOGD_CORE, "rd.net.dns-backend: invalid value '%s'", argument);
+ return;
+ }
+
+ reader->dns_backend = g_strdup(argument);
+}
+
+static void
+reader_parse_dns_resolve_mode(Reader *reader, const char *argument)
+{
+ if (!NM_IN_STRSET(argument, "backup", "prefer", "exclusive")) {
+ _LOGW(LOGD_CORE, "rd.net.dns-resolve-mode: invalid value '%s'", argument);
+ return;
+ }
+
+ reader->dns_resolve_mode = g_strdup(argument);
+}
+
static void
reader_parse_ethtool(Reader *reader, char *argument)
{
@@ -1410,7 +1436,9 @@ nmi_cmdline_reader_parse(const char *etc_connections_dir,
const char *const *argv,
char **hostname,
gint64 *carrier_timeout_sec,
- char ***global_dns_servers)
+ char ***global_dns_servers,
+ char **dns_backend,
+ char **dns_resolve_mode)
{
Reader *reader;
const char *tag;
@@ -1529,6 +1557,10 @@ nmi_cmdline_reader_parse(const char *etc_connections_dir,
reader_parse_ethtool(reader, argument);
} else if (nm_streq(tag, "rd.net.dns")) {
reader_parse_global_dns(reader, argument);
+ } else if (nm_streq(tag, "rd.net.dns-backend")) {
+ reader_parse_dns_backend(reader, argument);
+ } else if (nm_streq(tag, "rd.net.dns-resolve-mode")) {
+ reader_parse_dns_resolve_mode(reader, argument);
}
}
@@ -1643,8 +1675,9 @@ nmi_cmdline_reader_parse(const char *etc_connections_dir,
g_hash_table_foreach(reader->hash, _normalize_conn, NULL);
NM_SET_OUT(hostname, g_steal_pointer(&reader->hostname));
-
NM_SET_OUT(carrier_timeout_sec, reader->carrier_timeout_sec);
+ NM_SET_OUT(dns_backend, g_steal_pointer(&reader->dns_backend));
+ NM_SET_OUT(dns_resolve_mode, g_steal_pointer(&reader->dns_resolve_mode));
if (reader->global_dns) {
if (global_dns_servers) {
diff --git a/src/nm-initrd-generator/tests/test-cmdline-reader.c b/src/nm-initrd-generator/tests/test-cmdline-reader.c
index 07cf57bdaa..a0100764ca 100644
--- a/src/nm-initrd-generator/tests/test-cmdline-reader.c
+++ b/src/nm-initrd-generator/tests/test-cmdline-reader.c
@@ -23,7 +23,12 @@
/*****************************************************************************/
-#define _parse(ARGV, out_hostname, out_carrier_timeout_sec, _out_global_dns_servers) \
+#define _parse(ARGV, \
+ out_hostname, \
+ out_carrier_timeout_sec, \
+ _out_global_dns_servers, \
+ _out_dns_backend, \
+ _out_dns_resolve_mode) \
({ \
const char *const *const _ARGV = (ARGV); \
char **const _out_hostname = (out_hostname); \
@@ -35,8 +40,9 @@
_ARGV, \
_out_hostname, \
_out_carrier_timeout_sec, \
- _out_global_dns_servers); \
- \
+ _out_global_dns_servers, \
+ _out_dns_backend, \
+ _out_dns_resolve_mode); \
g_assert(_connections); \
\
_connections; \
@@ -51,6 +57,8 @@
_con_connections = _parse((ARGV), \
nmtst_get_rand_bool() ? &_con_hostname : NULL, \
nmtst_get_rand_bool() ? &_con_carrier_timeout_sec : NULL, \
+ NULL, \
+ NULL, \
NULL); \
g_assert_cmpstr(_con_hostname, ==, NULL); \
g_assert_cmpint(_con_carrier_timeout_sec, ==, 0); \
@@ -156,7 +164,7 @@ test_dhcp_with_hostname(void)
gs_free char *hostname = NULL;
gint64 carrier_timeout_sec = 0;
- connections = _parse(ARGV, &hostname, &carrier_timeout_sec, NULL);
+ connections = _parse(ARGV, &hostname, &carrier_timeout_sec, NULL, NULL, NULL);
g_assert_cmpint(g_hash_table_size(connections), ==, 1);
g_assert_cmpstr(hostname, ==, "host1");
g_assert_cmpint(carrier_timeout_sec, ==, 0);
@@ -426,7 +434,7 @@ test_if_ip4_manual(void)
gs_free char *hostname = NULL;
gint64 carrier_timeout_sec = 0;
- connections = _parse(ARGV, &hostname, &carrier_timeout_sec, NULL);
+ connections = _parse(ARGV, &hostname, &carrier_timeout_sec, NULL, NULL, NULL);
g_assert_cmpint(g_hash_table_size(connections), ==, 2);
g_assert_cmpstr(hostname, ==, "hostname1.example.com");
g_assert_cmpint(carrier_timeout_sec, ==, 0);
@@ -507,7 +515,7 @@ test_if_ip4_auto(void)
gs_free char *hostname = NULL;
gint64 carrier_timeout_sec = 0;
- connections = _parse(ARGV, &hostname, &carrier_timeout_sec, NULL);
+ connections = _parse(ARGV, &hostname, &carrier_timeout_sec, NULL, NULL, NULL);
g_assert_cmpint(g_hash_table_size(connections), ==, 1);
g_assert_cmpstr(hostname, ==, "myhostname");
g_assert_cmpint(carrier_timeout_sec, ==, 0);
@@ -598,7 +606,7 @@ test_if_ip6_manual(void)
gs_free char *hostname = NULL;
gint64 carrier_timeout_sec = 0;
- connections = _parse(ARGV, &hostname, &carrier_timeout_sec, NULL);
+ connections = _parse(ARGV, &hostname, &carrier_timeout_sec, NULL, NULL, NULL);
g_assert_cmpint(g_hash_table_size(connections), ==, 1);
g_assert_cmpstr(hostname, ==, "hostname0.example.com");
g_assert_cmpint(carrier_timeout_sec, ==, 0);
@@ -686,7 +694,7 @@ test_if_mac_ifname(void)
gs_free char *hostname = NULL;
gint64 carrier_timeout_sec = 0;
- connections = _parse(ARGV, &hostname, &carrier_timeout_sec, NULL);
+ connections = _parse(ARGV, &hostname, &carrier_timeout_sec, NULL, NULL, NULL);
g_assert_cmpint(g_hash_table_size(connections), ==, 1);
g_assert_cmpstr(hostname, ==, "hostname0");
g_assert_cmpint(carrier_timeout_sec, ==, 0);
@@ -1842,7 +1850,7 @@ test_rd_znet(void)
gs_free char *hostname = NULL;
gint64 carrier_timeout_sec = 0;
- connections = _parse(ARGV, &hostname, &carrier_timeout_sec, NULL);
+ connections = _parse(ARGV, &hostname, &carrier_timeout_sec, NULL, NULL, NULL);
g_assert_cmpint(g_hash_table_size(connections), ==, 2);
g_assert_cmpstr(hostname, ==, "foo.example.com");
g_assert_cmpint(carrier_timeout_sec, ==, 0);
@@ -1929,7 +1937,7 @@ test_rd_znet_legacy(void)
gs_free char *hostname = NULL;
gint64 carrier_timeout_sec = 0;
- connections = _parse(ARGV, &hostname, &carrier_timeout_sec, NULL);
+ connections = _parse(ARGV, &hostname, &carrier_timeout_sec, NULL, NULL, NULL);
g_assert_cmpint(g_hash_table_size(connections), ==, 2);
g_assert_cmpstr(hostname, ==, "foo.example.com");
g_assert_cmpint(carrier_timeout_sec, ==, 0);
@@ -2008,7 +2016,7 @@ test_rd_znet_ifnames(void)
gint64 carrier_timeout_sec = 0;
const char *const *v_subchannels;
- connections = _parse(ARGV, &hostname, &carrier_timeout_sec, NULL);
+ connections = _parse(ARGV, &hostname, &carrier_timeout_sec, NULL, NULL, NULL);
g_assert_cmpint(g_hash_table_size(connections), ==, 2);
connection = g_hash_table_lookup(connections, "zeth0");
@@ -2283,7 +2291,7 @@ test_nameserver(void)
gs_free char *hostname = NULL;
gint64 carrier_timeout_sec = 0;
- connections = _parse(ARGV, &hostname, &carrier_timeout_sec, NULL);
+ connections = _parse(ARGV, &hostname, &carrier_timeout_sec, NULL, NULL, NULL);
g_assert_cmpint(g_hash_table_size(connections), ==, 3);
g_assert_cmpstr(hostname, ==, "foo.example.com");
g_assert_cmpint(carrier_timeout_sec, ==, 0);
@@ -2462,7 +2470,7 @@ test_carrier_timeout(void)
gs_free char *hostname = NULL;
gint64 carrier_timeout_sec = 0;
- connections = _parse(ARGV, &hostname, &carrier_timeout_sec, NULL);
+ connections = _parse(ARGV, &hostname, &carrier_timeout_sec, NULL, NULL, NULL);
g_assert_cmpint(g_hash_table_size(connections), ==, 0);
g_assert_cmpstr(hostname, ==, NULL);
g_assert_cmpint(carrier_timeout_sec, ==, 20);
@@ -2475,13 +2483,22 @@ test_global_dns(void)
const char *const *ARGV = NM_MAKE_STRV("rd.net.dns=dns+tls://8.8.8.8",
"rd.net.dns=1.1.1.1",
"rd.net.dns=foobar",
- "rd.net.dns=dns+tls://[fd01::1]:35#name");
+ "rd.net.dns=dns+tls://[fd01::1]:35#name",
+ "rd.net.dns-backend=dnsconfd",
+ "rd.net.dns-resolve-mode=exclusive");
gs_free char *hostname = NULL;
gs_strfreev char **global_dns_servers = NULL;
+ gs_free char *dns_backend = NULL;
+ gs_free char *dns_resolve_mode = NULL;
gint64 carrier_timeout_sec = 0;
NMTST_EXPECT_NM_WARN("cmdline-reader: rd.net.dns: invalid server 'foobar'");
- connections = _parse(ARGV, &hostname, &carrier_timeout_sec, &global_dns_servers);
+ connections = _parse(ARGV,
+ &hostname,
+ &carrier_timeout_sec,
+ &global_dns_servers,
+ &dns_backend,
+ &dns_resolve_mode);
g_test_assert_expected_messages();
g_assert_cmpint(g_hash_table_size(connections), ==, 0);
@@ -2492,6 +2509,8 @@ test_global_dns(void)
g_assert_cmpstr(global_dns_servers[1], ==, "1.1.1.1");
g_assert_cmpstr(global_dns_servers[2], ==, "dns+tls://[fd01::1]:35#name");
g_assert_cmpstr(global_dns_servers[3], ==, NULL);
+ g_assert_cmpstr(dns_backend, ==, "dnsconfd");
+ g_assert_cmpstr(dns_resolve_mode, ==, "exclusive");
}
#define _ethtool_check_inval(arg) \