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) \