about summary refs log tree commit diff
path: root/src/initrd
diff options
context:
space:
mode:
Diffstat (limited to 'src/initrd')
-rw-r--r--src/initrd/nm-initrd-generator.c42
-rw-r--r--src/initrd/nm-initrd-generator.h2
-rw-r--r--src/initrd/nmi-cmdline-reader.c125
-rw-r--r--src/initrd/nmi-dt-reader.c14
-rw-r--r--src/initrd/nmi-ibft-reader.c9
-rw-r--r--src/initrd/tests/test-cmdline-reader.c120
6 files changed, 213 insertions, 99 deletions
diff --git a/src/initrd/nm-initrd-generator.c b/src/initrd/nm-initrd-generator.c
index dccb21f8..ac81dde0 100644
--- a/src/initrd/nm-initrd-generator.c
+++ b/src/initrd/nm-initrd-generator.c
@@ -33,7 +33,7 @@ output_conn (gpointer key, gpointer value, gpointer user_data)
 	if (!nm_connection_normalize (connection, NULL, NULL, &error))
 		goto err_out;
 
-	file = nm_keyfile_write (connection, NULL, NULL, &error);
+	file = nm_keyfile_write (connection, NM_KEYFILE_HANDLER_FLAGS_NONE, NULL, NULL, &error);
 	if (file == NULL)
 		goto err_out;
 
@@ -64,24 +64,28 @@ err_out:
 }
 
 #define DEFAULT_SYSFS_DIR        "/sys"
+#define DEFAULT_INITRD_DATA_DIR  NMRUNDIR "/initrd"
 
 int
 main (int argc, char *argv[])
 {
 	GHashTable *connections;
 	gs_free char *connections_dir = NULL;
+	gs_free char *initrd_dir = NULL;
 	gs_free char *sysfs_dir = NULL;
 	gboolean dump_to_stdout = FALSE;
 	gs_strfreev char **remaining = NULL;
 	GOptionEntry option_entries[] = {
-		{ "connections-dir", 'c', 0, G_OPTION_ARG_FILENAME, &connections_dir, "Output connection directory", NM_KEYFILE_PATH_NAME_RUN },
-		{ "sysfs-dir", 'd', 0, G_OPTION_ARG_FILENAME, &sysfs_dir, "The sysfs mount point", DEFAULT_SYSFS_DIR },
-		{ "stdout", 's', 0, G_OPTION_ARG_NONE, &dump_to_stdout, "Dump connections to standard output", NULL },
-		{ G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_STRING_ARRAY, &remaining, NULL, NULL },
+		{ "connections-dir",  'c',  0, G_OPTION_ARG_FILENAME,     &connections_dir, "Output connection directory",         NM_KEYFILE_PATH_NAME_RUN },
+		{ "initrd-data-dir",  'i',  0, G_OPTION_ARG_FILENAME,     &initrd_dir,      "Output initrd data directory",        DEFAULT_INITRD_DATA_DIR },
+		{ "sysfs-dir",        'd',  0, G_OPTION_ARG_FILENAME,     &sysfs_dir,       "The sysfs mount point",               DEFAULT_SYSFS_DIR },
+		{ "stdout",           's',  0, G_OPTION_ARG_NONE,         &dump_to_stdout,  "Dump connections to standard output", NULL },
+		{ G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_STRING_ARRAY, &remaining,       NULL,                                  NULL },
 		{ NULL }
 	};
 	GOptionContext *option_context;
-	GError *error = NULL;
+	gs_free_error GError *error = NULL;
+	gs_free char *hostname = NULL;
 	int errsv;
 
 	option_context = g_option_context_new ("-- [ip=...] [rd.route=...] [bridge=...] [bond=...] [team=...] [vlan=...] "
@@ -108,6 +112,8 @@ main (int argc, char *argv[])
 		connections_dir = g_strdup (NM_KEYFILE_PATH_NAME_RUN);
 	if (!sysfs_dir)
 		sysfs_dir = g_strdup (DEFAULT_SYSFS_DIR);
+	if (!initrd_dir)
+		initrd_dir = g_strdup (DEFAULT_INITRD_DATA_DIR);
 	if (dump_to_stdout)
 		nm_clear_g_free (&connections_dir);
 
@@ -117,9 +123,31 @@ main (int argc, char *argv[])
 		return 1;
 	}
 
-	connections = nmi_cmdline_reader_parse (sysfs_dir, (const char *const*) remaining);
+	connections = nmi_cmdline_reader_parse (sysfs_dir,
+	                                        (const char *const*) remaining,
+	                                        &hostname);
+
 	g_hash_table_foreach (connections, output_conn, connections_dir);
 	g_hash_table_destroy (connections);
 
+	if (g_mkdir_with_parents (initrd_dir, 0755) != 0) {
+		errsv = errno;
+		_LOGW (LOGD_CORE, "%s: %s", initrd_dir, nm_strerror_native (errsv));
+		return 1;
+	}
+
+	if (hostname) {
+		gs_free char *hostname_file = NULL;
+		gs_free char *data = NULL;
+
+		hostname_file = g_strdup_printf ("%s/hostname", initrd_dir);
+		data = g_strdup_printf ("%s\n", hostname);
+
+		if (!g_file_set_contents (hostname_file, data, strlen (data), &error)) {
+			_LOGW (LOGD_CORE, "%s: %s", hostname_file, error->message);
+			return 1;
+		}
+	}
+
 	return 0;
 }
diff --git a/src/initrd/nm-initrd-generator.h b/src/initrd/nm-initrd-generator.h
index cba383d1..97199921 100644
--- a/src/initrd/nm-initrd-generator.h
+++ b/src/initrd/nm-initrd-generator.h
@@ -28,6 +28,6 @@ gboolean nmi_ibft_update_connection_from_nic (NMConnection *connection, GHashTab
 
 NMConnection *nmi_dt_reader_parse (const char *sysfs_dir);
 
-GHashTable *nmi_cmdline_reader_parse (const char *sysfs_dir, const char *const*argv);
+GHashTable *nmi_cmdline_reader_parse (const char *sysfs_dir, const char *const*argv, char **hostname);
 
 #endif  /* __NM_INITRD_GENERATOR_H__ */
diff --git a/src/initrd/nmi-cmdline-reader.c b/src/initrd/nmi-cmdline-reader.c
index 2eb6d7e5..7513b4c9 100644
--- a/src/initrd/nmi-cmdline-reader.c
+++ b/src/initrd/nmi-cmdline-reader.c
@@ -7,6 +7,7 @@
 
 #include "nm-core-internal.h"
 #include "nm-initrd-generator.h"
+#include "systemd/nm-sd-utils-shared.h"
 
 /*****************************************************************************/
 
@@ -22,6 +23,11 @@ typedef struct {
 	GPtrArray *array;
 	NMConnection *bootdev_connection;   /* connection for bootdev=$ifname */
 	NMConnection *default_connection;   /* connection not bound to any ifname */
+	char *hostname;
+
+	/* Parameters to be set for all connections */
+	gboolean ignore_auto_dns;
+	int dhcp_timeout;
 } Reader;
 
 static Reader *
@@ -45,6 +51,7 @@ reader_destroy (Reader *reader, gboolean free_hash)
 
 	g_ptr_array_unref (reader->array);
 	hash = g_steal_pointer (&reader->hash);
+	nm_clear_g_free (&reader->hostname);
 	nm_g_slice_free (reader);
 	if (!free_hash)
 		return g_steal_pointer (&hash);
@@ -86,6 +93,8 @@ reader_create_connection (Reader *reader,
 	g_object_set (setting,
 	              NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO,
 	              NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE,
+	              NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS, reader->ignore_auto_dns,
+	              NM_SETTING_IP_CONFIG_DHCP_TIMEOUT, reader->dhcp_timeout,
 	              NULL);
 
 	setting = nm_setting_ip6_config_new ();
@@ -94,6 +103,8 @@ reader_create_connection (Reader *reader,
 	              NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO,
 	              NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE,
 	              NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE, (int) NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64,
+	              NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS, reader->ignore_auto_dns,
+	              NM_SETTING_IP_CONFIG_DHCP_TIMEOUT, reader->dhcp_timeout,
 	              NULL);
 
 	setting = nm_setting_connection_new ();
@@ -345,6 +356,14 @@ reader_parse_ip (Reader *reader, const char *sysfs_dir, char *argument)
 			ifname = tmp;
 		}
 
+		if (client_hostname && !nm_sd_hostname_is_valid (client_hostname, FALSE))
+			client_hostname = NULL;
+
+		if (client_hostname) {
+			g_free (reader->hostname);
+			reader->hostname = g_strdup (client_hostname);
+		}
+
 		/* <ifname>:{none|off|dhcp|on|any|dhcp6|auto6|ibft} */
 
 		kind = get_word (&argument, ':');
@@ -363,8 +382,8 @@ reader_parse_ip (Reader *reader, const char *sysfs_dir, char *argument)
 		}
 	}
 
-	if (ifname == NULL && (   g_strcmp0 (kind, "fw") == 0
-	                       || g_strcmp0 (kind, "ibft") == 0)) {
+	if (   ifname == NULL
+	    && NM_IN_STRSET (kind, "fw", "ibft")) {
 		reader_read_all_connections_from_fw (reader, sysfs_dir);
 		return;
 	}
@@ -442,7 +461,7 @@ reader_parse_ip (Reader *reader, const char *sysfs_dir, char *argument)
 	}
 
 	/* Dynamic IP configuration configured explicitly. */
-	if (g_strcmp0 (kind, "none") == 0 || (g_strcmp0 (kind, "off") == 0)) {
+	if (NM_IN_STRSET (kind, "none", "off")) {
 		if (nm_setting_ip_config_get_num_addresses (s_ip6) == 0) {
 			g_object_set (s_ip6,
 			              NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_DISABLED,
@@ -453,7 +472,7 @@ reader_parse_ip (Reader *reader, const char *sysfs_dir, char *argument)
 			              NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_DISABLED,
 			              NULL);
 		}
-	} else if (g_strcmp0 (kind, "dhcp") == 0) {
+	} else if (nm_streq0 (kind, "dhcp")) {
 		g_object_set (s_ip4,
 		              NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO,
 		              NM_SETTING_IP_CONFIG_MAY_FAIL, FALSE,
@@ -463,7 +482,7 @@ reader_parse_ip (Reader *reader, const char *sysfs_dir, char *argument)
 			              NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE,
 			              NULL);
 		}
-	} else if (g_strcmp0 (kind, "dhcp6") == 0) {
+	} else if (nm_streq0 (kind, "dhcp6")) {
 		g_object_set (s_ip6,
 		              NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_DHCP,
 		              NM_SETTING_IP_CONFIG_MAY_FAIL, FALSE,
@@ -473,7 +492,7 @@ reader_parse_ip (Reader *reader, const char *sysfs_dir, char *argument)
 			              NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_DISABLED,
 			              NULL);
 		}
-	} else if (g_strcmp0 (kind, "auto6") == 0) {
+	} else if (nm_streq0 (kind, "auto6")) {
 		g_object_set (s_ip4,
 		              NM_SETTING_IP_CONFIG_MAY_FAIL, FALSE,
 		              NULL);
@@ -482,7 +501,7 @@ reader_parse_ip (Reader *reader, const char *sysfs_dir, char *argument)
 			              NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_DISABLED,
 			              NULL);
 		}
-	} else if (g_strcmp0 (kind, "ibft") == 0) {
+	} else if (nm_streq0 (kind, "ibft")) {
 		gs_free char *address_path = g_build_filename (sysfs_dir, "class", "net", ifname, "address", NULL);
 		gs_free char *mac, *mac_up = NULL;
 		GHashTable *nic = NULL;
@@ -591,7 +610,7 @@ reader_parse_master (Reader *reader,
 	s_con = nm_connection_get_setting_connection (connection);
 	master = nm_setting_connection_get_uuid (s_con);
 
-	if (strcmp (type_name, NM_SETTING_BOND_SETTING_NAME) == 0) {
+	if (nm_streq (type_name, NM_SETTING_BOND_SETTING_NAME)) {
 		s_bond = (NMSettingBond *)nm_connection_get_setting_by_name (connection, type_name);
 
 		opts = get_word (&argument, ':');
@@ -777,7 +796,9 @@ reader_parse_rd_znet (Reader *reader, char *argument, gboolean net_ifnames)
 		ifname = g_strdup_printf ("%s%d", prefix, index);
 	}
 
-	connection = reader_get_connection (reader, ifname, NM_SETTING_WIRED_SETTING_NAME, TRUE);
+	connection = reader_get_connection (reader, ifname, NM_SETTING_WIRED_SETTING_NAME, FALSE);
+	if (!connection)
+		return;
 	s_wired = nm_connection_get_setting_wired (connection);
 	g_object_set (s_wired,
 	              NM_SETTING_WIRED_S390_NETTYPE, nettype,
@@ -808,27 +829,6 @@ _normalize_conn (gpointer key, gpointer value, gpointer user_data)
 }
 
 static void
-reader_set_ignore_auto_dns (Reader *reader)
-{
-	GHashTableIter iter;
-	NMConnection *connection;
-	NMSettingIPConfig *s_ip = NULL;
-
-	g_hash_table_iter_init (&iter, reader->hash);
-	while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &connection)) {
-		s_ip = nm_connection_get_setting_ip4_config (connection);
-		g_object_set (s_ip,
-		              NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS, TRUE,
-		              NULL);
-
-		s_ip = nm_connection_get_setting_ip6_config (connection);
-		g_object_set (s_ip,
-		              NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS, TRUE,
-		              NULL);
-	}
-}
-
-static void
 reader_add_nameservers (Reader *reader, GPtrArray *nameservers)
 {
 	NMConnection *connection;
@@ -875,7 +875,7 @@ reader_add_nameservers (Reader *reader, GPtrArray *nameservers)
 }
 
 GHashTable *
-nmi_cmdline_reader_parse (const char *sysfs_dir, const char *const*argv)
+nmi_cmdline_reader_parse (const char *sysfs_dir, const char *const*argv, char **hostname)
 {
 	Reader *reader;
 	const char *tag;
@@ -886,16 +886,28 @@ nmi_cmdline_reader_parse (const char *sysfs_dir, const char *const*argv)
 	gboolean net_ifnames = TRUE;
 	gs_unref_ptrarray GPtrArray *nameservers = NULL;
 	gs_unref_ptrarray GPtrArray *routes = NULL;
-	gboolean ignore_auto_dns = FALSE;
+	gs_unref_ptrarray GPtrArray *znets = NULL;
 	int i;
 
 	reader = reader_new ();
 
 	for (i = 0; argv[i]; i++) {
-		if (strcmp (argv[i], "net.ifnames=0") == 0)
-			net_ifnames = FALSE;
-		else if (g_str_has_prefix (argv[i], "net.ifnames="))
-			net_ifnames = TRUE;
+		gs_free char *argument_clone = NULL;
+		char *argument;
+
+		argument_clone = g_strdup (argv[i]);
+		argument = argument_clone;
+
+		tag = get_word (&argument, '=');
+
+		if (nm_streq (tag, "net.ifnames"))
+			net_ifnames = !nm_streq (argument, "0");
+		else if (nm_streq (tag, "rd.peerdns"))
+			reader->ignore_auto_dns = !_nm_utils_ascii_str_to_bool (argument, TRUE);
+		else if (nm_streq (tag, "rd.net.timeout.dhcp")) {
+			reader->dhcp_timeout = _nm_utils_ascii_str_to_int64 (argument,
+			                                                     10, 0, G_MAXINT32, 0);
+		}
 	}
 
 	for (i = 0; argv[i]; i++) {
@@ -907,24 +919,24 @@ nmi_cmdline_reader_parse (const char *sysfs_dir, const char *const*argv)
 		argument = argument_clone;
 
 		tag = get_word (&argument, '=');
-		if (strcmp (tag, "ip") == 0)
+		if (nm_streq (tag, "ip"))
 			reader_parse_ip (reader, sysfs_dir, argument);
-		else if (strcmp (tag, "rd.route") == 0) {
+		else if (nm_streq (tag, "rd.route")) {
 			if (!routes)
 				routes = g_ptr_array_new_with_free_func (g_free);
 			g_ptr_array_add (routes, g_strdup (argument));
-		} else if (strcmp (tag, "bridge") == 0)
+		} else if (nm_streq (tag, "bridge"))
 			reader_parse_master (reader, argument, NM_SETTING_BRIDGE_SETTING_NAME, "br");
-		else if (strcmp (tag, "bond") == 0)
+		else if (nm_streq (tag, "bond"))
 			reader_parse_master (reader, argument, NM_SETTING_BOND_SETTING_NAME, NULL);
-		else if (strcmp (tag, "team") == 0)
+		else if (nm_streq (tag, "team"))
 			reader_parse_master (reader, argument, NM_SETTING_TEAM_SETTING_NAME, NULL);
-		else if (strcmp (tag, "vlan") == 0)
+		else if (nm_streq (tag, "vlan"))
 			reader_parse_vlan (reader, argument);
-		else if (strcmp (tag, "bootdev") == 0) {
+		else if (nm_streq (tag, "bootdev")) {
 			g_free (bootdev);
 			bootdev = g_strdup (argument);
-		} else if (strcmp (tag, "nameserver") == 0) {
+		} else if (nm_streq (tag, "nameserver")) {
 			word = get_word (&argument, '\0');
 			if (word) {
 				if (!nameservers)
@@ -933,17 +945,17 @@ nmi_cmdline_reader_parse (const char *sysfs_dir, const char *const*argv)
 			}
 			if (argument && *argument)
 				_LOGW (LOGD_CORE, "Ignoring extra: '%s'.", argument);
-		} else if (strcmp (tag, "rd.peerdns") == 0)
-			ignore_auto_dns = !_nm_utils_ascii_str_to_bool (argument, TRUE);
-		else if (strcmp (tag, "rd.iscsi.ibft") == 0 && _nm_utils_ascii_str_to_bool (argument, TRUE))
+		} else if (nm_streq (tag, "rd.iscsi.ibft") && _nm_utils_ascii_str_to_bool (argument, TRUE))
 			reader_read_all_connections_from_fw (reader, sysfs_dir);
-		else if (strcmp (tag, "rd.bootif") == 0)
+		else if (nm_streq (tag, "rd.bootif"))
 			ignore_bootif = !_nm_utils_ascii_str_to_bool (argument, TRUE);
-		else if (strcmp (tag, "rd.neednet") == 0)
+		else if (nm_streq (tag, "rd.neednet"))
 			neednet = _nm_utils_ascii_str_to_bool (argument, TRUE);
-		else if (strcmp (tag, "rd.znet") == 0)
-			reader_parse_rd_znet (reader, argument, net_ifnames);
-		else if (g_ascii_strcasecmp (tag, "BOOTIF") == 0) {
+		else if (nm_streq (tag, "rd.znet")) {
+			if (!znets)
+				znets = g_ptr_array_new_with_free_func (g_free);
+			g_ptr_array_add (znets, g_strdup (argument));
+		} else if (g_ascii_strcasecmp (tag, "BOOTIF") == 0) {
 			nm_clear_g_free (&bootif_val);
 			bootif_val = g_strdup (argument);
 		}
@@ -1009,9 +1021,14 @@ nmi_cmdline_reader_parse (const char *sysfs_dir, const char *const*argv)
 	if (nameservers)
 		reader_add_nameservers (reader, nameservers);
 
-	if (ignore_auto_dns)
-		reader_set_ignore_auto_dns (reader);
+	if (znets) {
+		for (i = 0; i < znets->len; i++)
+			reader_parse_rd_znet (reader, znets->pdata[i], net_ifnames);
+	}
 
 	g_hash_table_foreach (reader->hash, _normalize_conn, NULL);
+
+	NM_SET_OUT (hostname, g_steal_pointer (&reader->hostname));
+
 	return reader_destroy (reader, FALSE);
 }
diff --git a/src/initrd/nmi-dt-reader.c b/src/initrd/nmi-dt-reader.c
index f118adc3..205cc0b5 100644
--- a/src/initrd/nmi-dt-reader.c
+++ b/src/initrd/nmi-dt-reader.c
@@ -156,7 +156,7 @@ nmi_dt_reader_parse (const char *sysfs_dir)
 
 	local_hwaddr = dt_get_hwaddr_property (base, bootpath, "local-mac-address");
 	hwaddr = dt_get_hwaddr_property (base, bootpath, "mac-address");
-	if (g_strcmp0 (local_hwaddr, hwaddr) == 0)
+	if (nm_streq0 (local_hwaddr, hwaddr))
 		nm_clear_g_free (&local_hwaddr);
 
 	tokens = g_strsplit (path, ",", 0);
@@ -169,10 +169,10 @@ nmi_dt_reader_parse (const char *sysfs_dir)
 
 	for (i = 0; tokens[i]; i++) {
 		/* Skip these. They have magical meaning for OpenFirmware. */
-		if (   strcmp (tokens[i], "nfs") == 0
-		    || strcmp (tokens[i], "last") == 0)
+		if (NM_IN_STRSET (tokens[i], "nfs",
+		                             "last"))
 			continue;
-		if (strcmp (tokens[i], "promiscuous") == 0) {
+		if (nm_streq (tokens[i], "promiscuous")) {
 			/* Ignore. */
 			continue;
 		}
@@ -201,9 +201,9 @@ nmi_dt_reader_parse (const char *sysfs_dir)
 	 */
 
 	for (; tokens[i]; i++) {
-		if (   strcmp (tokens[i], "bootp") == 0
-		    || strcmp (tokens[i], "dhcp") == 0
-		    || strcmp (tokens[i], "rarp") == 0) {
+		if (NM_IN_STRSET (tokens[i], "bootp",
+		                             "dhcp",
+		                             "rarp")) {
 			bootp = TRUE;
 			continue;
 		}
diff --git a/src/initrd/nmi-ibft-reader.c b/src/initrd/nmi-ibft-reader.c
index 477bc0bf..fe6f6432 100644
--- a/src/initrd/nmi-ibft-reader.c
+++ b/src/initrd/nmi-ibft-reader.c
@@ -17,7 +17,6 @@
 #include <unistd.h>
 
 #include "nm-core-internal.h"
-#include "platform/nm-platform.h"
 #include "NetworkManagerUtils.h"
 
 /*****************************************************************************/
@@ -185,12 +184,12 @@ ip_setting_add_from_block (GHashTable *nic,
 		return FALSE;
 	}
 
-	if (   (g_strcmp0 (s_origin, "3") == 0 && family == AF_INET)
-	    || (g_strcmp0 (s_origin, "4") == 0 && family == AF_INET)) {
+	if (   (nm_streq0 (s_origin, "3") && family == AF_INET)
+	    || (nm_streq0 (s_origin, "4") && family == AF_INET)) {
 		method = NM_SETTING_IP4_CONFIG_METHOD_AUTO;
-	} else if (g_strcmp0 (s_origin, "3") == 0 && family == AF_INET6) {
+	} else if (nm_streq0 (s_origin, "3") && family == AF_INET6) {
 		method = NM_SETTING_IP6_CONFIG_METHOD_DHCP;
-	} else if (g_strcmp0 (s_origin, "4") == 0 && family == AF_INET6) {
+	} else if (nm_streq0 (s_origin, "4") && family == AF_INET6) {
 		method = NM_SETTING_IP6_CONFIG_METHOD_AUTO;
 	} else if (family == AF_INET) {
 		method = NM_SETTING_IP4_CONFIG_METHOD_MANUAL;
diff --git a/src/initrd/tests/test-cmdline-reader.c b/src/initrd/tests/test-cmdline-reader.c
index b2b06e27..5379c3a3 100644
--- a/src/initrd/tests/test-cmdline-reader.c
+++ b/src/initrd/tests/test-cmdline-reader.c
@@ -30,10 +30,12 @@ test_auto (void)
 	NMSettingWired *s_wired;
 	NMSettingIPConfig *s_ip4;
 	NMSettingIPConfig *s_ip6;
+	gs_free char *hostname = NULL;
 
-	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV);
+	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV, &hostname);
 	g_assert (connections);
 	g_assert_cmpint (g_hash_table_size (connections), ==, 1);
+	g_assert_cmpstr (hostname, ==, NULL);
 
 	connection = g_hash_table_lookup (connections, "default_connection");
 	g_assert (connection);
@@ -81,10 +83,12 @@ test_if_auto_with_mtu (void)
 	NMSettingWired *s_wired;
 	NMSettingIPConfig *s_ip4;
 	NMSettingIPConfig *s_ip6;
+	gs_free char *hostname = NULL;
 
-	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV);
+	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV, &hostname);
 	g_assert (connections);
 	g_assert_cmpint (g_hash_table_size (connections), ==, 1);
+	g_assert_cmpstr (hostname, ==, NULL);
 
 	connection = g_hash_table_lookup (connections, "eth0");
 	g_assert (connection);
@@ -115,10 +119,13 @@ test_if_dhcp6 (void)
 	NMConnection *connection;
 	NMSettingIPConfig *s_ip4;
 	NMSettingIPConfig *s_ip6;
+	gs_free char *hostname = NULL;
 
-	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV);
+	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV, &hostname);
 	g_assert (connections);
 	g_assert_cmpint (g_hash_table_size (connections), ==, 1);
+	g_assert_cmpstr (hostname, ==, NULL);
+
 	connection = g_hash_table_lookup (connections, "eth1");
 	g_assert (connection);
 	nmtst_assert_connection_verifies_without_normalization (connection);
@@ -145,10 +152,12 @@ test_if_auto_with_mtu_and_mac (void)
 	NMSettingWired *s_wired;
 	NMSettingIPConfig *s_ip4;
 	NMSettingIPConfig *s_ip6;
+	gs_free char *hostname = NULL;
 
-	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV);
+	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV, &hostname);
 	g_assert (connections);
 	g_assert_cmpint (g_hash_table_size (connections), ==, 1);
+	g_assert_cmpstr (hostname, ==, NULL);
 
 	connection = g_hash_table_lookup (connections, "eth2");
 	g_assert (connection);
@@ -183,10 +192,12 @@ test_if_ip4_manual (void)
 	NMConnection *connection;
 	NMSettingIPConfig *s_ip4;
 	NMIPAddress *ip_addr;
+	gs_free char *hostname = NULL;
 
-	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV);
+	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV, &hostname);
 	g_assert (connections);
 	g_assert_cmpint (g_hash_table_size (connections), ==, 2);
+	g_assert_cmpstr (hostname, ==, "hostname1.example.com");
 
 	connection = g_hash_table_lookup (connections, "eth3");
 	g_assert (connection);
@@ -237,10 +248,12 @@ test_if_ip6_manual (void)
 	NMConnection *connection;
 	NMSettingIPConfig *s_ip6;
 	NMIPAddress *ip_addr;
+	gs_free char *hostname = NULL;
 
-	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV);
+	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV, &hostname);
 	g_assert (connections);
 	g_assert_cmpint (g_hash_table_size (connections), ==, 1);
+	g_assert_cmpstr (hostname, ==, "hostname0.example.com");
 
 	connection = g_hash_table_lookup (connections, "eth4");
 	g_assert (connection);
@@ -274,10 +287,12 @@ test_multiple_merge (void)
 	NMSettingIPConfig *s_ip4;
 	NMSettingIPConfig *s_ip6;
 	NMIPAddress *ip_addr;
+	gs_free char *hostname = NULL;
 
-	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV);
+	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV, &hostname);
 	g_assert (connections);
 	g_assert_cmpint (g_hash_table_size (connections), ==, 1);
+	g_assert_cmpstr (hostname, ==, NULL);
 
 	connection = g_hash_table_lookup (connections, "eth0");
 	g_assert (connection);
@@ -317,10 +332,12 @@ test_multiple_bootdev (void)
 	NMConnection *connection;
 	NMSettingIPConfig *s_ip4;
 	NMSettingIPConfig *s_ip6;
+	gs_free char *hostname = NULL;
 
-	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV);
+	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV, &hostname);
 	g_assert (connections);
 	g_assert_cmpint (g_hash_table_size (connections), ==, 2);
+	g_assert_cmpstr (hostname, ==, NULL);
 
 	connection = g_hash_table_lookup (connections, "eth3");
 	g_assert (connection);
@@ -344,10 +361,12 @@ test_bootdev (void)
 	const char *const*ARGV = NM_MAKE_STRV ("vlan=vlan2:ens5", "bootdev=ens3");
 	NMConnection *connection;
 	NMSettingConnection *s_con;
+	gs_free char *hostname = NULL;
 
-	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV);
+	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV, &hostname);
 	g_assert (connections);
 	g_assert_cmpint (g_hash_table_size (connections), ==, 2);
+	g_assert_cmpstr (hostname, ==, NULL);
 
 	connection = g_hash_table_lookup (connections, "ens3");
 	g_assert (connection);
@@ -384,10 +403,12 @@ test_some_more (void)
 	NMSettingIPConfig *s_ip4;
 	NMSettingIPConfig *s_ip6;
 	NMIPRoute *ip_route;
+	gs_free char *hostname = NULL;
 
-	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV);
+	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV, &hostname);
 	g_assert (connections);
 	g_assert_cmpint (g_hash_table_size (connections), ==, 2);
+	g_assert_cmpstr (hostname, ==, NULL);
 
 	connection = g_hash_table_lookup (connections, "eth1");
 	g_assert (connection);
@@ -466,10 +487,12 @@ test_bond (void)
 	NMSettingBond *s_bond;
 	NMIPRoute *ip_route;
 	const char *master_uuid;
+	gs_free char *hostname = NULL;
 
-	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV);
+	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV, &hostname);
 	g_assert (connections);
 	g_assert_cmpint (g_hash_table_size (connections), ==, 3);
+	g_assert_cmpstr (hostname, ==, NULL);
 
 	connection = g_hash_table_lookup (connections, "bong0");
 	g_assert (connection);
@@ -545,10 +568,12 @@ test_bond_default (void)
 	NMSettingIPConfig *s_ip6;
 	NMSettingBond *s_bond;
 	const char *master_uuid;
+	gs_free char *hostname = NULL;
 
-	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV);
+	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV, &hostname);
 	g_assert (connections);
 	g_assert_cmpint (g_hash_table_size (connections), ==, 2);
+	g_assert_cmpstr (hostname, ==, NULL);
 
 	connection = g_hash_table_lookup (connections, "bond0");
 
@@ -598,7 +623,9 @@ static void
 test_bridge (void)
 {
 	gs_unref_hashtable GHashTable *connections = NULL;
-	const char *const*ARGV = NM_MAKE_STRV ("bridge=bridge0:eth0,eth1", "rd.route=192.0.2.53::bridge0");
+	const char *const*ARGV = NM_MAKE_STRV ("bridge=bridge0:eth0,eth1",
+	                                       "rd.route=192.0.2.53::bridge0",
+	                                       "rd.net.timeout.dhcp=10");
 	NMConnection *connection;
 	NMSettingConnection *s_con;
 	NMSettingIPConfig *s_ip4;
@@ -606,10 +633,12 @@ test_bridge (void)
 	NMSettingBridge *s_bridge;
 	NMIPRoute *ip_route;
 	const char *master_uuid;
+	gs_free char *hostname = NULL;
 
-	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV);
+	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV, &hostname);
 	g_assert (connections);
 	g_assert_cmpint (g_hash_table_size (connections), ==, 3);
+	g_assert_cmpstr (hostname, ==, NULL);
 
 	connection = g_hash_table_lookup (connections, "bridge0");
 	g_assert (connection);
@@ -626,6 +655,7 @@ test_bridge (void)
 	g_assert_cmpint (nm_setting_ip_config_get_num_dns (s_ip4), ==, 0);
 	g_assert (!nm_setting_ip_config_get_gateway (s_ip4));
 	g_assert_cmpint (nm_setting_ip_config_get_num_routes (s_ip4), ==, 1);
+	g_assert_cmpint (nm_setting_ip_config_get_dhcp_timeout(s_ip4), ==, 10);
 	ip_route = nm_setting_ip_config_get_route (s_ip4, 0);
 	g_assert_cmpstr (nm_ip_route_get_dest (ip_route), ==, "192.0.2.53");
 	g_assert_cmpint (nm_ip_route_get_family (ip_route), ==, AF_INET);
@@ -640,6 +670,8 @@ test_bridge (void)
 	g_assert_cmpint (nm_setting_ip_config_get_num_dns (s_ip6), ==, 0);
 	g_assert (!nm_setting_ip_config_get_gateway (s_ip6));
 	g_assert_cmpint (nm_setting_ip_config_get_num_routes (s_ip6), ==, 0);
+	g_assert_cmpint (nm_setting_ip_config_get_dhcp_timeout(s_ip6), ==, 10);
+
 
 	s_bridge = nm_connection_get_setting_bridge (connection);
 	g_assert (s_bridge);
@@ -682,10 +714,12 @@ test_bridge_default (void)
 	NMSettingIPConfig *s_ip6;
 	NMSettingBridge *s_bridge;
 	const char *master_uuid;
+	gs_free char *hostname = NULL;
 
-	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV);
+	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV, &hostname);
 	g_assert (connections);
 	g_assert_cmpint (g_hash_table_size (connections), ==, 2);
+	g_assert_cmpstr (hostname, ==, NULL);
 
 	connection = g_hash_table_lookup (connections, "br0");
 
@@ -740,10 +774,12 @@ test_team (void)
 	NMSettingIPConfig *s_ip6;
 	NMSettingTeam *s_team;
 	const char *master_uuid;
+	gs_free char *hostname = NULL;
 
-	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV);
+	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV, &hostname);
 	g_assert (connections);
 	g_assert_cmpint (g_hash_table_size (connections), ==, 3);
+	g_assert_cmpstr (hostname, ==, NULL);
 
 	connection = g_hash_table_lookup (connections, "team0");
 	g_assert (connection);
@@ -806,10 +842,12 @@ test_ibft_ip_dev (void)
 	gs_unref_hashtable GHashTable *connections = NULL;
 	NMSettingConnection *s_con;
 	NMConnection *connection;
+	gs_free char *hostname = NULL;
 
-	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV);
+	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV, &hostname);
 	g_assert (connections);
 	g_assert_cmpint (g_hash_table_size (connections), ==, 1);
+	g_assert_cmpstr (hostname, ==, NULL);
 
 	connection = g_hash_table_lookup (connections, "eth0");
 	g_assert (connection);
@@ -825,10 +863,12 @@ _test_ibft_ip (const char *const*ARGV)
 {
 	gs_unref_hashtable GHashTable *connections = NULL;
 	NMConnection *connection;
+	gs_free char *hostname = NULL;
 
-	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV);
+	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV, &hostname);
 	g_assert (connections);
 	g_assert_cmpint (g_hash_table_size (connections), ==, 2);
+	g_assert_cmpstr (hostname, ==, NULL);
 
 	connection = g_hash_table_lookup (connections, "ibft0");
 	g_assert (connection);
@@ -864,10 +904,12 @@ test_ignore_extra (void)
 {
 	gs_unref_hashtable GHashTable *connections = NULL;
 	const char *const*ARGV = NM_MAKE_STRV ("blabla", "extra", "lalala");
+	gs_free char *hostname = NULL;
 
-	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV);
+	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV, &hostname);
 	g_assert (connections);
 	g_assert_cmpint (g_hash_table_size (connections), ==, 0);
+	g_assert_cmpstr (hostname, ==, NULL);
 }
 
 static void
@@ -875,6 +917,7 @@ test_rd_znet (void)
 {
 	gs_unref_hashtable GHashTable *connections = NULL;
 	const char *const*const ARGV = NM_MAKE_STRV ("ip=10.11.12.13::10.11.12.1:24:foo.example.com:enc800:none",
+	                                             "ip=slc600:dhcp",
 	                                             "rd.znet=qeth,0.0.0800,0.0.0801,0.0.0802,layer2=0,portno=1",
 	                                             "rd.znet=ctc,0.0.0600,0.0.0601,layer2=0,portno=0");
 	NMConnection *connection;
@@ -886,10 +929,12 @@ test_rd_znet (void)
 		{ .name = "portno", .value_str = "1" },
 	};
 	int i_s390_options_keys;
+	gs_free char *hostname = NULL;
 
-	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV);
+	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV, &hostname);
 	g_assert (connections);
 	g_assert_cmpint (g_hash_table_size (connections), ==, 2);
+	g_assert_cmpstr (hostname, ==, "foo.example.com");
 
 	connection = g_hash_table_lookup (connections, "enc800");
 	g_assert (NM_IS_CONNECTION (connection));
@@ -960,13 +1005,16 @@ test_rd_znet_legacy (void)
 	const char *const*const ARGV = NM_MAKE_STRV ("ip=10.11.12.13::10.11.12.1:24:foo.example.com:eth0:none",
 	                                             "rd.znet=qeth,0.0.0800,0.0.0801,0.0.0802,layer2=0,portno=1",
 	                                             "rd.znet=ctc,0.0.0600,0.0.0601,layer2=0,portno=0",
+	                                             "ip=ctc0:dhcp",
 	                                             "net.ifnames=0");
 	NMConnection *connection;
 	NMSettingConnection *s_con;
+	gs_free char *hostname = NULL;
 
-	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV);
+	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV, &hostname);
 	g_assert (connections);
 	g_assert_cmpint (g_hash_table_size (connections), ==, 2);
+	g_assert_cmpstr (hostname, ==, "foo.example.com");
 
 	connection = g_hash_table_lookup (connections, "eth0");
 	g_assert (NM_IS_CONNECTION (connection));
@@ -992,6 +1040,19 @@ test_rd_znet_legacy (void)
 }
 
 static void
+test_rd_znet_no_ip (void)
+{
+	gs_unref_hashtable GHashTable *connections = NULL;
+	const char *const*const ARGV = NM_MAKE_STRV ("rd.znet=qeth,0.0.0800,0.0.0801,0.0.0802,layer2=0,portno=1");
+	gs_free char *hostname = NULL;
+
+	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV, &hostname);
+	g_assert (connections);
+	g_assert_cmpint (g_hash_table_size (connections), ==, 0);
+	g_assert_cmpstr (hostname, ==, NULL);
+}
+
+static void
 test_bootif (void)
 {
 	gs_unref_hashtable GHashTable *connections = NULL;
@@ -1001,10 +1062,12 @@ test_bootif (void)
 	NMSettingWired *s_wired;
 	NMSettingIPConfig *s_ip4;
 	NMSettingIPConfig *s_ip6;
+	gs_free char *hostname = NULL;
 
-	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV);
+	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV, &hostname);
 	g_assert (connections);
 	g_assert_cmpint (g_hash_table_size (connections), ==, 1);
+	g_assert_cmpstr (hostname, ==, NULL);
 
 	connection = g_hash_table_lookup (connections, "default_connection");
 	g_assert (connection);
@@ -1037,10 +1100,12 @@ test_bootif_hwtype (void)
 	NMSettingWired *s_wired;
 	NMSettingIPConfig *s_ip4;
 	NMSettingIPConfig *s_ip6;
+	gs_free char *hostname = NULL;
 
-	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV);
+	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV, &hostname);
 	g_assert (connections);
 	g_assert_cmpint (g_hash_table_size (connections), ==, 2);
+	g_assert_cmpstr (hostname, ==, NULL);
 
 	connection = g_hash_table_lookup (connections, "eth0");
 	g_assert (connection);
@@ -1100,10 +1165,12 @@ test_nameserver (void)
 	                                       "nameserver=[2606:4700:4700::1111]");
 	NMConnection *connection;
 	NMSettingIPConfig *s_ip;
+	gs_free char *hostname = NULL;
 
-	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV);
+	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV, &hostname);
 	g_assert (connections);
 	g_assert_cmpint (g_hash_table_size (connections), ==, 3);
+	g_assert_cmpstr (hostname, ==, "foo.example.com");
 
 	connection = g_hash_table_lookup (connections, "eth0");
 	g_assert (connection);
@@ -1140,10 +1207,12 @@ test_bootif_off (void)
 {
 	gs_unref_hashtable GHashTable *connections = NULL;
 	const char *const*ARGV = NM_MAKE_STRV ("BOOTIF=01-00-53-AB-cd-02-03", "rd.bootif=0");
+	gs_free char *hostname = NULL;
 
-	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV);
+	connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV, &hostname);
 	g_assert (connections);
 	g_assert_cmpint (g_hash_table_size (connections), ==, 0);
+	g_assert_cmpstr (hostname, ==, NULL);
 }
 
 NMTST_DEFINE ();
@@ -1174,6 +1243,7 @@ int main (int argc, char **argv)
 	g_test_add_func ("/initrd/cmdline/ignore_extra", test_ignore_extra);
 	g_test_add_func ("/initrd/cmdline/rd_znet", test_rd_znet);
 	g_test_add_func ("/initrd/cmdline/rd_znet/legacy", test_rd_znet_legacy);
+	g_test_add_func ("/initrd/cmdline/rd_znet/no_ip", test_rd_znet_no_ip);
 	g_test_add_func ("/initrd/cmdline/bootif", test_bootif);
 	g_test_add_func ("/initrd/cmdline/bootif/hwtype", test_bootif_hwtype);
 	g_test_add_func ("/initrd/cmdline/bootif/off", test_bootif_off);