From d0e0213a08cba903cfa1993b0dce678d0dd54528 Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Wed, 25 Mar 2020 18:34:01 +0100 Subject: [PATCH 1/7] initrd: don't add empty connection if iBFT parsing fails Don't add an empty connection to the list if nmi_ibft_update_connection_from_nic() fails when reading iBFT information. If the function fails in parse_ip(), continue with the existing connection built from other command line options. Also, fix a memory leak. --- src/initrd/nmi-cmdline-reader.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/initrd/nmi-cmdline-reader.c b/src/initrd/nmi-cmdline-reader.c index bc870d65df..a60bdc9892 100644 --- a/src/initrd/nmi-cmdline-reader.c +++ b/src/initrd/nmi-cmdline-reader.c @@ -198,7 +198,7 @@ static void read_all_connections_from_fw (GHashTable *connections, const char *sysfs_dir) { gs_unref_hashtable GHashTable *ibft = NULL; - NMConnection *connection; + NMConnection *dt_connection; GHashTableIter iter; const char *mac; GHashTable *nic; @@ -209,8 +209,9 @@ read_all_connections_from_fw (GHashTable *connections, const char *sysfs_dir) g_hash_table_iter_init (&iter, ibft); while (g_hash_table_iter_next (&iter, (gpointer *) &mac, (gpointer *) &nic)) { - connection = nm_simple_connection_new (); + gs_unref_object NMConnection *connection = NULL; + connection = nm_simple_connection_new (); index = g_hash_table_lookup (nic, "index"); if (!index) { _LOGW (LOGD_CORE, "Ignoring an iBFT entry without an index"); @@ -220,18 +221,19 @@ read_all_connections_from_fw (GHashTable *connections, const char *sysfs_dir) if (!nmi_ibft_update_connection_from_nic (connection, nic, &error)) { _LOGW (LOGD_CORE, "Unable to merge iBFT configuration: %s", error->message); g_error_free (error); + continue; } g_hash_table_insert (connections, g_strdup_printf ("ibft%s", index), - connection); + g_steal_pointer (&connection)); } - connection = nmi_dt_reader_parse (sysfs_dir); - if (connection) { + dt_connection = nmi_dt_reader_parse (sysfs_dir); + if (dt_connection) { g_hash_table_insert (connections, g_strdup ("ofw"), - connection); + dt_connection); } } From bba7663407a6224aca73735194b7f6f0cf74521e Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Mon, 23 Mar 2020 18:13:40 +0100 Subject: [PATCH 2/7] initrd: generate ipv6.method=ignore connection with ip=dhcp The legacy network module used to leave kernel IPv6 autoconfiguration enabled with ip=dhcp. Do the same for backwards compatibility. https://github.com/dracutdevs/dracut/issues/700 --- src/initrd/nmi-cmdline-reader.c | 2 +- src/initrd/tests/test-cmdline-reader.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/initrd/nmi-cmdline-reader.c b/src/initrd/nmi-cmdline-reader.c index a60bdc9892..9a27887b61 100644 --- a/src/initrd/nmi-cmdline-reader.c +++ b/src/initrd/nmi-cmdline-reader.c @@ -392,7 +392,7 @@ parse_ip (GHashTable *connections, const char *sysfs_dir, char *argument) NULL); 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, + NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE, NULL); } } else if (g_strcmp0 (kind, "dhcp6") == 0) { diff --git a/src/initrd/tests/test-cmdline-reader.c b/src/initrd/tests/test-cmdline-reader.c index 8951e4913e..6725e2c995 100644 --- a/src/initrd/tests/test-cmdline-reader.c +++ b/src/initrd/tests/test-cmdline-reader.c @@ -991,7 +991,7 @@ test_bootif (void) s_ip6 = nm_connection_get_setting_ip6_config (connection); g_assert (s_ip6); - g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_DISABLED); + g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_IGNORE); g_assert (!nm_setting_ip_config_get_ignore_auto_dns (s_ip6)); } @@ -1027,7 +1027,7 @@ test_bootif_hwtype (void) s_ip6 = nm_connection_get_setting_ip6_config (connection); g_assert (s_ip6); - g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_DISABLED); + g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_IGNORE); g_assert (!nm_setting_ip_config_get_ignore_auto_dns (s_ip6)); connection = g_hash_table_lookup (connections, "bootif_connection"); From 6a8c6ed674b9381fa3eb4feceef58382d0e7dff5 Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Wed, 25 Mar 2020 09:19:03 +0100 Subject: [PATCH 3/7] initrd: fix indentation in iBFT reader --- src/initrd/nmi-ibft-reader.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/initrd/nmi-ibft-reader.c b/src/initrd/nmi-ibft-reader.c index ca44b399f0..477bc0bf5d 100644 --- a/src/initrd/nmi-ibft-reader.c +++ b/src/initrd/nmi-ibft-reader.c @@ -200,8 +200,8 @@ ip_setting_add_from_block (GHashTable *nic, g_return_val_if_reached (FALSE); } g_object_set (s_ip, - NM_SETTING_IP_CONFIG_METHOD, method, - NM_SETTING_IP_CONFIG_MAY_FAIL, FALSE, + NM_SETTING_IP_CONFIG_METHOD, method, + NM_SETTING_IP_CONFIG_MAY_FAIL, FALSE, NULL); if (s_gateway && !nm_utils_ipaddr_is_valid (family, s_gateway)) { From 9b5322b33c8b51758246f758b20570b8d05dd44b Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Sat, 21 Mar 2020 09:57:57 +0100 Subject: [PATCH 4/7] initrd: keep connections sorted Connections are kept in a hash table indexed by name. This causes non deterministic output in get_conn() when we have to decide a default connection and no bootdev was specified on the command line. Also add an array that stores the original order in which interfaces appear in the command line, and use it when we have to loop through connections. The return value of nmi_cmdline_reader_parse() is still a hash table because once we have generated connections, their order doesn't matter. --- src/initrd/nmi-cmdline-reader.c | 200 ++++++++++++++++++++------------ 1 file changed, 123 insertions(+), 77 deletions(-) diff --git a/src/initrd/nmi-cmdline-reader.c b/src/initrd/nmi-cmdline-reader.c index 9a27887b61..023d154f33 100644 --- a/src/initrd/nmi-cmdline-reader.c +++ b/src/initrd/nmi-cmdline-reader.c @@ -17,33 +17,65 @@ /*****************************************************************************/ -static gboolean -_connection_matches_type (gpointer key, gpointer value, gpointer user_data) -{ - NMConnection *connection = value; - const char *type_name = user_data; - NMSettingConnection *s_con; +typedef struct { + GHashTable *hash; + GPtrArray *array; +} Reader; - s_con = nm_connection_get_setting_connection (connection); - if (type_name == NULL) - return nm_setting_connection_get_master (s_con) == NULL; - else - return strcmp (nm_setting_connection_get_connection_type (s_con), type_name) == 0; +static Reader * +reader_new (void) +{ + Reader *reader; + + reader = g_slice_new (Reader); + *reader = (Reader) { + .hash = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, g_object_unref), + .array = g_ptr_array_new (), + }; + + return reader; +} + +static GHashTable * +reader_destroy (Reader *reader, gboolean free_hash) +{ + gs_unref_hashtable GHashTable *hash = NULL; + + g_ptr_array_unref (reader->array); + hash = g_steal_pointer (&reader->hash); + nm_g_slice_free (reader); + if (!free_hash) + return g_steal_pointer (&hash); + return NULL; } static NMConnection * -add_conn (GHashTable *connections, - const char *basename, - const char *id, - const char *ifname, - const char *type_name, - NMConnectionMultiConnect multi_connect) +add_connection (Reader *reader, const char *name, NMConnection *connection_take) +{ + char *name_dup; + + name_dup = g_strdup (name); + if (g_hash_table_insert (reader->hash, name_dup, connection_take)) + g_ptr_array_add (reader->array, name_dup); + + return connection_take; +} + +/* Returns a new connection owned by the reader */ +static NMConnection * +create_connection (Reader *reader, + const char *basename, + const char *id, + const char *ifname, + const char *type_name, + NMConnectionMultiConnect multi_connect) { NMConnection *connection; NMSetting *setting; - connection = nm_simple_connection_new (); - g_hash_table_insert (connections, g_strdup (basename), connection); + connection = add_connection (reader, + basename, + nm_simple_connection_new ()); /* Start off assuming dynamic IP configurations. */ @@ -76,7 +108,7 @@ add_conn (GHashTable *connections, } static NMConnection * -get_conn (GHashTable *connections, const char *ifname, const char *type_name) +get_connection (Reader *reader, const char *ifname, const char *type_name) { NMConnection *connection; NMSetting *setting; @@ -92,26 +124,44 @@ get_conn (GHashTable *connections, const char *ifname, const char *type_name) multi_connect = NM_CONNECTION_MULTI_CONNECT_MULTIPLE; } - connection = g_hash_table_lookup (connections, (gpointer) basename); + connection = g_hash_table_lookup (reader->hash, (gpointer) basename); if (!connection && !ifname) { + NMConnection *candidate; + NMSettingConnection *s_con; + guint i; + /* * If ifname was not given, we'll match the connection by type. * If the type was not given either, then we're happy with any connection but slaves. * This is so that things like "bond=bond0:eth1,eth2 nameserver=1.3.3.7 end up * slapping the nameserver to the most reasonable connection (bond0). */ - connection = g_hash_table_find (connections, - _connection_matches_type, - (gpointer) type_name); + + for (i = 0; i < reader->array->len; i++) { + candidate = g_hash_table_lookup (reader->hash, reader->array->pdata[i]); + s_con = nm_connection_get_setting_connection (candidate); + + if ( type_name == NULL + && nm_setting_connection_get_master (s_con) == NULL) { + connection = candidate; + break; + } + + if ( type_name != NULL + && nm_streq (nm_setting_connection_get_connection_type (s_con), type_name)) { + connection = candidate; + break; + } + } } if (!connection) { if (!type_name) type_name = NM_SETTING_WIRED_SETTING_NAME; - connection = add_conn (connections, basename, - ifname ?: "Wired Connection", - ifname, type_name, multi_connect); + connection = create_connection (reader, basename, + ifname ?: "Wired Connection", + ifname, type_name, multi_connect); } setting = (NMSetting *)nm_connection_get_setting_connection (connection); @@ -195,7 +245,7 @@ _base_setting_set (NMConnection *connection, const char *property, const char *v } static void -read_all_connections_from_fw (GHashTable *connections, const char *sysfs_dir) +read_all_connections_from_fw (Reader *reader, const char *sysfs_dir) { gs_unref_hashtable GHashTable *ibft = NULL; NMConnection *dt_connection; @@ -210,6 +260,7 @@ read_all_connections_from_fw (GHashTable *connections, const char *sysfs_dir) g_hash_table_iter_init (&iter, ibft); while (g_hash_table_iter_next (&iter, (gpointer *) &mac, (gpointer *) &nic)) { gs_unref_object NMConnection *connection = NULL; + gs_free char *name = NULL; connection = nm_simple_connection_new (); index = g_hash_table_lookup (nic, "index"); @@ -224,21 +275,17 @@ read_all_connections_from_fw (GHashTable *connections, const char *sysfs_dir) continue; } - g_hash_table_insert (connections, - g_strdup_printf ("ibft%s", index), - g_steal_pointer (&connection)); + name = g_strdup_printf ("ibft%s", index); + add_connection (reader, name, g_steal_pointer (&connection)); } dt_connection = nmi_dt_reader_parse (sysfs_dir); - if (dt_connection) { - g_hash_table_insert (connections, - g_strdup ("ofw"), - dt_connection); - } + if (dt_connection) + add_connection (reader, "ofw", dt_connection); } static void -parse_ip (GHashTable *connections, const char *sysfs_dir, char *argument) +parse_ip (Reader *reader, const char *sysfs_dir, char *argument) { NMConnection *connection; NMSettingIPConfig *s_ip4 = NULL, *s_ip6 = NULL; @@ -301,12 +348,12 @@ parse_ip (GHashTable *connections, const char *sysfs_dir, char *argument) if (ifname == NULL && ( g_strcmp0 (kind, "fw") == 0 || g_strcmp0 (kind, "ibft") == 0)) { - read_all_connections_from_fw (connections, sysfs_dir); + read_all_connections_from_fw (reader, sysfs_dir); return; } /* Parsing done, construct the NMConnection. */ - connection = get_conn (connections, ifname, NULL); + connection = get_connection (reader, ifname, NULL); s_ip4 = nm_connection_get_setting_ip4_config (connection); s_ip6 = nm_connection_get_setting_ip6_config (connection); @@ -497,7 +544,7 @@ parse_ip (GHashTable *connections, const char *sysfs_dir, char *argument) } static void -parse_master (GHashTable *connections, +parse_master (Reader *reader, char *argument, const char *type_name, const char *default_name) @@ -519,7 +566,7 @@ parse_master (GHashTable *connections, master = master_to_free = g_strdup_printf ("%s0", default_name ?: type_name); slaves = get_word (&argument, ':'); - connection = get_conn (connections, master, type_name); + connection = get_connection (reader, master, type_name); s_con = nm_connection_get_setting_connection (connection); master = nm_setting_connection_get_uuid (s_con); @@ -541,7 +588,7 @@ parse_master (GHashTable *connections, if (slave == NULL) slave = "eth0"; - connection = get_conn (connections, slave, NULL); + connection = get_connection (reader, slave, NULL); s_con = nm_connection_get_setting_connection (connection); g_object_set (s_con, NM_SETTING_CONNECTION_SLAVE_TYPE, type_name, @@ -556,7 +603,7 @@ parse_master (GHashTable *connections, } static void -parse_rd_route (GHashTable *connections, char *argument) +parse_rd_route (Reader *reader, char *argument) { NMConnection *connection; const char *net; @@ -574,7 +621,7 @@ parse_rd_route (GHashTable *connections, char *argument) gateway = get_word (&argument, ':'); interface = get_word (&argument, ':'); - connection = get_conn (connections, interface, NULL); + connection = get_connection (reader, interface, NULL); if (net && *net) { if (!nm_utils_parse_inaddr_prefix_bin (family, net, &family, &net_addr, &net_prefix)) { @@ -618,7 +665,7 @@ parse_rd_route (GHashTable *connections, char *argument) } static void -parse_vlan (GHashTable *connections, char *argument) +parse_vlan (Reader *reader, char *argument) { NMConnection *connection; NMSettingVlan *s_vlan; @@ -634,7 +681,7 @@ parse_vlan (GHashTable *connections, char *argument) break; } - connection = get_conn (connections, vlan, NM_SETTING_VLAN_SETTING_NAME); + connection = get_connection (reader, vlan, NM_SETTING_VLAN_SETTING_NAME); s_vlan = nm_connection_get_setting_vlan (connection); g_object_set (s_vlan, @@ -647,18 +694,18 @@ parse_vlan (GHashTable *connections, char *argument) } static void -parse_bootdev (GHashTable *connections, char *argument) +parse_bootdev (Reader *reader, char *argument) { NMConnection *connection; NMSettingConnection *s_con; - connection = get_conn (connections, NULL, NULL); + connection = get_connection (reader, NULL, NULL); if ( nm_connection_get_interface_name (connection) && strcmp (nm_connection_get_interface_name (connection), argument) != 0) { /* If the default connection already has an interface name, * we should not overwrite it. Create a new one instead. */ - connection = get_conn (connections, argument, NULL); + connection = get_connection (reader, argument, NULL); } s_con = nm_connection_get_setting_connection (connection); @@ -668,13 +715,13 @@ parse_bootdev (GHashTable *connections, char *argument) } static void -parse_nameserver (GHashTable *connections, char *argument) +parse_nameserver (Reader *reader, char *argument) { NMConnection *connection; NMSettingIPConfig *s_ip = NULL; char *dns; - connection = get_conn (connections, NULL, NULL); + connection = get_connection (reader, NULL, NULL); dns = get_word (&argument, '\0'); @@ -697,13 +744,13 @@ parse_nameserver (GHashTable *connections, char *argument) } static void -parse_rd_peerdns (GHashTable *connections, char *argument) +parse_rd_peerdns (Reader *reader, char *argument) { gboolean auto_dns = !_nm_utils_ascii_str_to_bool (argument, TRUE); NMConnection *connection; NMSettingIPConfig *s_ip = NULL; - connection = get_conn (connections, NULL, NULL); + connection = get_connection (reader, NULL, NULL); s_ip = nm_connection_get_setting_ip4_config (connection); g_object_set (s_ip, @@ -717,7 +764,7 @@ parse_rd_peerdns (GHashTable *connections, char *argument) } static void -parse_rd_znet (GHashTable *connections, char *argument, gboolean net_ifnames) +parse_rd_znet (Reader *reader, char *argument, gboolean net_ifnames) { const char *nettype; const char *subchannels[4] = { 0, 0, 0, 0 }; @@ -767,7 +814,7 @@ parse_rd_znet (GHashTable *connections, char *argument, gboolean net_ifnames) ifname = g_strdup_printf ("%s%d", prefix, index); } - connection = get_conn (connections, ifname, NM_SETTING_WIRED_SETTING_NAME); + connection = get_connection (reader, ifname, NM_SETTING_WIRED_SETTING_NAME); s_wired = nm_connection_get_setting_wired (connection); g_object_set (s_wired, NM_SETTING_WIRED_S390_NETTYPE, nettype, @@ -800,7 +847,7 @@ _normalize_conn (gpointer key, gpointer value, gpointer user_data) GHashTable * nmi_cmdline_reader_parse (const char *sysfs_dir, const char *const*argv) { - GHashTable *connections; + Reader *reader; const char *tag; gboolean ignore_bootif = FALSE; gboolean neednet = FALSE; @@ -808,7 +855,7 @@ nmi_cmdline_reader_parse (const char *sysfs_dir, const char *const*argv) gboolean net_ifnames = TRUE; int i; - connections = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, g_object_unref); + reader = reader_new (); for (i = 0; argv[i]; i++) { if (strcmp (argv[i], "net.ifnames=0") == 0) @@ -826,31 +873,31 @@ nmi_cmdline_reader_parse (const char *sysfs_dir, const char *const*argv) tag = get_word (&argument, '='); if (strcmp (tag, "ip") == 0) - parse_ip (connections, sysfs_dir, argument); + parse_ip (reader, sysfs_dir, argument); else if (strcmp (tag, "rd.route") == 0) - parse_rd_route (connections, argument); + parse_rd_route (reader, argument); else if (strcmp (tag, "bridge") == 0) - parse_master (connections, argument, NM_SETTING_BRIDGE_SETTING_NAME, "br"); + parse_master (reader, argument, NM_SETTING_BRIDGE_SETTING_NAME, "br"); else if (strcmp (tag, "bond") == 0) - parse_master (connections, argument, NM_SETTING_BOND_SETTING_NAME, NULL); + parse_master (reader, argument, NM_SETTING_BOND_SETTING_NAME, NULL); else if (strcmp (tag, "team") == 0) - parse_master (connections, argument, NM_SETTING_TEAM_SETTING_NAME, NULL); + parse_master (reader, argument, NM_SETTING_TEAM_SETTING_NAME, NULL); else if (strcmp (tag, "vlan") == 0) - parse_vlan (connections, argument); + parse_vlan (reader, argument); else if (strcmp (tag, "bootdev") == 0) - parse_bootdev (connections, argument); + parse_bootdev (reader, argument); else if (strcmp (tag, "nameserver") == 0) - parse_nameserver (connections, argument); + parse_nameserver (reader, argument); else if (strcmp (tag, "rd.peerdns") == 0) - parse_rd_peerdns (connections, argument); + parse_rd_peerdns (reader, argument); else if (strcmp (tag, "rd.iscsi.ibft") == 0 && _nm_utils_ascii_str_to_bool (argument, TRUE)) - read_all_connections_from_fw (connections, sysfs_dir); + read_all_connections_from_fw (reader, sysfs_dir); else if (strcmp (tag, "rd.bootif") == 0) ignore_bootif = !_nm_utils_ascii_str_to_bool (argument, TRUE); else if (strcmp (tag, "rd.neednet") == 0) neednet = _nm_utils_ascii_str_to_bool (argument, TRUE); else if (strcmp (tag, "rd.znet") == 0) - parse_rd_znet (connections, argument, net_ifnames); + parse_rd_znet (reader, argument, net_ifnames); else if (g_ascii_strcasecmp (tag, "BOOTIF") == 0) { nm_clear_g_free (&bootif_val); bootif_val = g_strdup (argument); @@ -874,16 +921,16 @@ nmi_cmdline_reader_parse (const char *sysfs_dir, const char *const*argv) bootif += 3; } - connection = get_conn (connections, NULL, NM_SETTING_WIRED_SETTING_NAME); + connection = get_connection (reader, NULL, NM_SETTING_WIRED_SETTING_NAME); s_wired = nm_connection_get_setting_wired (connection); if ( nm_connection_get_interface_name (connection) || ( nm_setting_wired_get_mac_address (s_wired) && !nm_utils_hwaddr_matches (nm_setting_wired_get_mac_address (s_wired), -1, bootif, -1))) { - connection = add_conn (connections, "bootif_connection", "BOOTIF Connection", - NULL, NM_SETTING_WIRED_SETTING_NAME, - NM_CONNECTION_MULTI_CONNECT_SINGLE); + connection = create_connection (reader, "bootif_connection", "BOOTIF Connection", + NULL, NM_SETTING_WIRED_SETTING_NAME, + NM_CONNECTION_MULTI_CONNECT_SINGLE); s_wired = (NMSettingWired *) nm_setting_wired_new (); nm_connection_add_setting (connection, (NMSetting *) s_wired); } @@ -892,12 +939,11 @@ nmi_cmdline_reader_parse (const char *sysfs_dir, const char *const*argv) NM_SETTING_WIRED_MAC_ADDRESS, bootif, NULL); } - if (neednet && g_hash_table_size (connections) == 0) { + if (neednet && g_hash_table_size (reader->hash) == 0) { /* Make sure there's some connection. */ - get_conn (connections, NULL, NM_SETTING_WIRED_SETTING_NAME); + get_connection (reader, NULL, NM_SETTING_WIRED_SETTING_NAME); } - g_hash_table_foreach (connections, _normalize_conn, NULL); - - return connections; + g_hash_table_foreach (reader->hash, _normalize_conn, NULL); + return reader_destroy (reader, FALSE); } From f3c9ee921ec8680dbefb9168884c871c91ba3dc6 Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Sat, 21 Mar 2020 15:33:29 +0100 Subject: [PATCH 5/7] initrd: sort ibft connections Instead of adding ibft connections in a random order to the list, sort them alphabetically. --- src/initrd/nmi-cmdline-reader.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/initrd/nmi-cmdline-reader.c b/src/initrd/nmi-cmdline-reader.c index 023d154f33..f3bebdd416 100644 --- a/src/initrd/nmi-cmdline-reader.c +++ b/src/initrd/nmi-cmdline-reader.c @@ -249,19 +249,22 @@ read_all_connections_from_fw (Reader *reader, const char *sysfs_dir) { gs_unref_hashtable GHashTable *ibft = NULL; NMConnection *dt_connection; - GHashTableIter iter; const char *mac; GHashTable *nic; const char *index; GError *error = NULL; + guint i, length; + gs_free const char **keys = NULL; ibft = nmi_ibft_read (sysfs_dir); + keys = nm_utils_strdict_get_keys (ibft, TRUE, &length); - g_hash_table_iter_init (&iter, ibft); - while (g_hash_table_iter_next (&iter, (gpointer *) &mac, (gpointer *) &nic)) { + for (i = 0; i < length; i++) { gs_unref_object NMConnection *connection = NULL; gs_free char *name = NULL; + mac = keys[i]; + nic = g_hash_table_lookup (ibft, mac); connection = nm_simple_connection_new (); index = g_hash_table_lookup (nic, "index"); if (!index) { From 25a2b6e14ff525be9838f4b0d90680e49b145f2b Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Sat, 21 Mar 2020 22:28:31 +0100 Subject: [PATCH 6/7] initrd: rework command line parsing The 'default_connection' created by the command line parser has multiple purposes. It's the connection created for 'ip=' arguments without command line, but is also created when there is a 'bootdev=' or for 'nameserver=' and no other connection exists at the moment the argument is parsed. This is confusing and leads to a result that depends on the order of parameters. For example: $ /usr/libexec/nm-initrd-generator -c connections -- bootdev=eth1 ip=eth0:dhcp $ ls connections/ default_connection.nmconnection eth0.nmconnection $ /usr/libexec/nm-initrd-generator -c connections -- ip=eth0:dhcp bootdev=eth1 $ ls connections/ eth0.nmconnection eth1.nmconnection Make this more explicit by tracking 'bootdev_connection' and 'default_connection' individually. Also fix handling of 'nameserver', 'rd.peerdns' and 'rd.route' arguments. First process all connections, and then set those properties. In particular, now nameservers are applied to all connections. https://gitlab.freedesktop.org/NetworkManager/NetworkManager/issues/391 --- src/initrd/nmi-cmdline-reader.c | 369 ++++++++++++++----------- src/initrd/tests/test-cmdline-reader.c | 97 ++++++- 2 files changed, 306 insertions(+), 160 deletions(-) diff --git a/src/initrd/nmi-cmdline-reader.c b/src/initrd/nmi-cmdline-reader.c index f3bebdd416..49b5126b6e 100644 --- a/src/initrd/nmi-cmdline-reader.c +++ b/src/initrd/nmi-cmdline-reader.c @@ -20,6 +20,8 @@ typedef struct { GHashTable *hash; GPtrArray *array; + NMConnection *bootdev_connection; /* connection for bootdev=$ifname */ + NMConnection *default_connection; /* connection not bound to any ifname */ } Reader; static Reader * @@ -108,24 +110,32 @@ create_connection (Reader *reader, } static NMConnection * -get_connection (Reader *reader, const char *ifname, const char *type_name) +get_default_connection (Reader *reader) { - NMConnection *connection; - NMSetting *setting; - const char *basename; - NMConnectionMultiConnect multi_connect; + NMConnection *con; - if (ifname) { - basename = ifname; - multi_connect = NM_CONNECTION_MULTI_CONNECT_SINGLE; - } else { - /* This is essentially for the "ip=dhcp" scenario. */ - basename = "default_connection"; - multi_connect = NM_CONNECTION_MULTI_CONNECT_MULTIPLE; + if (!reader->default_connection) { + con = create_connection (reader, + "default_connection", + "Wired Connection", + NULL, + NM_SETTING_WIRED_SETTING_NAME, + NM_CONNECTION_MULTI_CONNECT_MULTIPLE); + reader->default_connection = con; } + return reader->default_connection; +} - connection = g_hash_table_lookup (reader->hash, (gpointer) basename); - if (!connection && !ifname) { +static NMConnection * +get_connection (Reader *reader, + const char *ifname, + const char *type_name, + gboolean create_if_missing) +{ + NMConnection *connection = NULL; + NMSetting *setting; + + if (!ifname) { NMConnection *candidate; NMSettingConnection *s_con; guint i; @@ -136,7 +146,6 @@ get_connection (Reader *reader, const char *ifname, const char *type_name) * This is so that things like "bond=bond0:eth1,eth2 nameserver=1.3.3.7 end up * slapping the nameserver to the most reasonable connection (bond0). */ - for (i = 0; i < reader->array->len; i++) { candidate = g_hash_table_lookup (reader->hash, reader->array->pdata[i]); s_con = nm_connection_get_setting_connection (candidate); @@ -153,17 +162,22 @@ get_connection (Reader *reader, const char *ifname, const char *type_name) break; } } - } + } else + connection = g_hash_table_lookup (reader->hash, (gpointer) ifname); if (!connection) { + if (!create_if_missing) + return NULL; + if (!type_name) type_name = NM_SETTING_WIRED_SETTING_NAME; - connection = create_connection (reader, basename, + connection = create_connection (reader, ifname, ifname ?: "Wired Connection", - ifname, type_name, multi_connect); + ifname, type_name, + NM_CONNECTION_MULTI_CONNECT_SINGLE); } - setting = (NMSetting *)nm_connection_get_setting_connection (connection); + setting = (NMSetting *) nm_connection_get_setting_connection (connection); if (type_name) { g_object_set (setting, NM_SETTING_CONNECTION_TYPE, type_name, NULL); @@ -356,7 +370,11 @@ parse_ip (Reader *reader, const char *sysfs_dir, char *argument) } /* Parsing done, construct the NMConnection. */ - connection = get_connection (reader, ifname, NULL); + if (ifname) + connection = get_connection (reader, ifname, NULL, TRUE); + else + connection = get_default_connection (reader); + s_ip4 = nm_connection_get_setting_ip4_config (connection); s_ip6 = nm_connection_get_setting_ip6_config (connection); @@ -569,7 +587,7 @@ parse_master (Reader *reader, master = master_to_free = g_strdup_printf ("%s0", default_name ?: type_name); slaves = get_word (&argument, ':'); - connection = get_connection (reader, master, type_name); + connection = get_connection (reader, master, type_name, TRUE); s_con = nm_connection_get_setting_connection (connection); master = nm_setting_connection_get_uuid (s_con); @@ -591,7 +609,7 @@ parse_master (Reader *reader, if (slave == NULL) slave = "eth0"; - connection = get_connection (reader, slave, NULL); + connection = get_connection (reader, slave, NULL, TRUE); s_con = nm_connection_get_setting_connection (connection); g_object_set (s_con, NM_SETTING_CONNECTION_SLAVE_TYPE, type_name, @@ -606,65 +624,77 @@ parse_master (Reader *reader, } static void -parse_rd_route (Reader *reader, char *argument) +add_routes (Reader *reader, GPtrArray *array) { - NMConnection *connection; - const char *net; - const char *gateway; - const char *interface; - int family = AF_UNSPEC; - NMIPAddr net_addr = { }; - NMIPAddr gateway_addr = { }; - int net_prefix = -1; - NMIPRoute *route; - NMSettingIPConfig *s_ip; - GError *error = NULL; + guint i; - net = get_word (&argument, ':'); - gateway = get_word (&argument, ':'); - interface = get_word (&argument, ':'); + for (i = 0; i < array->len; i++) { + NMConnection *connection = NULL; + const char *net; + const char *gateway; + const char *interface; + int family = AF_UNSPEC; + NMIPAddr net_addr = { }; + NMIPAddr gateway_addr = { }; + int net_prefix = -1; + NMIPRoute *route; + NMSettingIPConfig *s_ip; + char *argument; + gs_free_error GError *error = NULL; - connection = get_connection (reader, interface, NULL); + argument = array->pdata[i]; + net = get_word (&argument, ':'); + gateway = get_word (&argument, ':'); + interface = get_word (&argument, ':'); - if (net && *net) { - if (!nm_utils_parse_inaddr_prefix_bin (family, net, &family, &net_addr, &net_prefix)) { - _LOGW (LOGD_CORE, "Unrecognized address: %s", net); - return; + if (interface) + connection = get_connection (reader, interface, NULL, TRUE); + if (!connection) + connection = reader->bootdev_connection; + if (!connection) + connection = get_connection (reader, interface, NULL, FALSE); + if (!connection) + connection = get_default_connection (reader); + + if (net && *net) { + if (!nm_utils_parse_inaddr_prefix_bin (family, net, &family, &net_addr, &net_prefix)) { + _LOGW (LOGD_CORE, "Unrecognized address: %s", net); + continue; + } } - } - if (gateway && *gateway) { - if (!nm_utils_parse_inaddr_bin (family, gateway, &family, &gateway_addr)) { - _LOGW (LOGD_CORE, "Unrecognized address: %s", gateway); - return; + if (gateway && *gateway) { + if (!nm_utils_parse_inaddr_bin (family, gateway, &family, &gateway_addr)) { + _LOGW (LOGD_CORE, "Unrecognized address: %s", gateway); + continue; + } } - } - switch (family) { - case AF_INET: - s_ip = nm_connection_get_setting_ip4_config (connection); - if (net_prefix == -1) - net_prefix = 32; - break; - case AF_INET6: - s_ip = nm_connection_get_setting_ip6_config (connection); - if (net_prefix == -1) - net_prefix = 128; - break; - default: - _LOGW (LOGD_CORE, "Unknown address family: %s", net); - return; - } + switch (family) { + case AF_INET: + s_ip = nm_connection_get_setting_ip4_config (connection); + if (net_prefix == -1) + net_prefix = 32; + break; + case AF_INET6: + s_ip = nm_connection_get_setting_ip6_config (connection); + if (net_prefix == -1) + net_prefix = 128; + break; + default: + _LOGW (LOGD_CORE, "Unknown address family: %s", net); + continue; + } - route = nm_ip_route_new_binary (family, &net_addr.addr_ptr, net_prefix, &gateway_addr.addr_ptr, -1, &error); - if (!route) { - g_warning ("Invalid route '%s via %s': %s\n", net, gateway, error->message); - g_clear_error (&error); - return; - } + route = nm_ip_route_new_binary (family, &net_addr.addr_ptr, net_prefix, &gateway_addr.addr_ptr, -1, &error); + if (!route) { + g_warning ("Invalid route '%s via %s': %s\n", net, gateway, error->message); + continue; + } - nm_setting_ip_config_add_route (s_ip, route); - nm_ip_route_unref (route); + nm_setting_ip_config_add_route (s_ip, route); + nm_ip_route_unref (route); + } } static void @@ -684,7 +714,7 @@ parse_vlan (Reader *reader, char *argument) break; } - connection = get_connection (reader, vlan, NM_SETTING_VLAN_SETTING_NAME); + connection = get_connection (reader, vlan, NM_SETTING_VLAN_SETTING_NAME, TRUE); s_vlan = nm_connection_get_setting_vlan (connection); g_object_set (s_vlan, @@ -696,76 +726,6 @@ parse_vlan (Reader *reader, char *argument) _LOGW (LOGD_CORE, "Ignoring extra: '%s'.", argument); } -static void -parse_bootdev (Reader *reader, char *argument) -{ - NMConnection *connection; - NMSettingConnection *s_con; - - connection = get_connection (reader, NULL, NULL); - - if ( nm_connection_get_interface_name (connection) - && strcmp (nm_connection_get_interface_name (connection), argument) != 0) { - /* If the default connection already has an interface name, - * we should not overwrite it. Create a new one instead. */ - connection = get_connection (reader, argument, NULL); - } - - s_con = nm_connection_get_setting_connection (connection); - g_object_set (s_con, - NM_SETTING_CONNECTION_INTERFACE_NAME, argument, - NULL); -} - -static void -parse_nameserver (Reader *reader, char *argument) -{ - NMConnection *connection; - NMSettingIPConfig *s_ip = NULL; - char *dns; - - connection = get_connection (reader, NULL, NULL); - - dns = get_word (&argument, '\0'); - - switch (guess_ip_address_family (dns)) { - case AF_INET: - s_ip = nm_connection_get_setting_ip4_config (connection); - break; - case AF_INET6: - s_ip = nm_connection_get_setting_ip6_config (connection); - break; - default: - _LOGW (LOGD_CORE, "Unknown address family: %s", dns); - break; - } - - nm_setting_ip_config_add_dns (s_ip, dns); - - if (argument && *argument) - _LOGW (LOGD_CORE, "Ignoring extra: '%s'.", argument); -} - -static void -parse_rd_peerdns (Reader *reader, char *argument) -{ - gboolean auto_dns = !_nm_utils_ascii_str_to_bool (argument, TRUE); - NMConnection *connection; - NMSettingIPConfig *s_ip = NULL; - - connection = get_connection (reader, NULL, NULL); - - s_ip = nm_connection_get_setting_ip4_config (connection); - g_object_set (s_ip, - NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS, auto_dns, - NULL); - - s_ip = nm_connection_get_setting_ip6_config (connection); - g_object_set (s_ip, - NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS, auto_dns, - NULL); -} - static void parse_rd_znet (Reader *reader, char *argument, gboolean net_ifnames) { @@ -817,7 +777,7 @@ parse_rd_znet (Reader *reader, char *argument, gboolean net_ifnames) ifname = g_strdup_printf ("%s%d", prefix, index); } - connection = get_connection (reader, ifname, NM_SETTING_WIRED_SETTING_NAME); + connection = get_connection (reader, ifname, NM_SETTING_WIRED_SETTING_NAME, TRUE); s_wired = nm_connection_get_setting_wired (connection); g_object_set (s_wired, NM_SETTING_WIRED_S390_NETTYPE, nettype, @@ -847,6 +807,72 @@ _normalize_conn (gpointer key, gpointer value, gpointer user_data) nm_connection_normalize (connection, NULL, NULL, NULL); } +static void +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 +add_nameservers (Reader *reader, GPtrArray *nameservers) +{ + NMConnection *connection; + NMSettingIPConfig *s_ip; + GHashTableIter iter; + int addr_family; + const char *ns; + guint i; + + for (i = 0; i < nameservers->len; i++) { + ns = nameservers->pdata[i]; + addr_family = guess_ip_address_family (ns); + if (addr_family == AF_UNSPEC) { + _LOGW (LOGD_CORE, "Unknown address family: %s", ns); + continue; + } + + g_hash_table_iter_init (&iter, reader->hash); + while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &connection)) { + switch (addr_family) { + case AF_INET: + s_ip = nm_connection_get_setting_ip4_config (connection); + if (!NM_IN_STRSET (nm_setting_ip_config_get_method (s_ip), + NM_SETTING_IP4_CONFIG_METHOD_AUTO, + NM_SETTING_IP4_CONFIG_METHOD_MANUAL)) + continue; + break; + case AF_INET6: + s_ip = nm_connection_get_setting_ip6_config (connection); + if (!NM_IN_STRSET (nm_setting_ip_config_get_method (s_ip), + NM_SETTING_IP6_CONFIG_METHOD_AUTO, + NM_SETTING_IP6_CONFIG_METHOD_DHCP, + NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) + continue; + break; + default: + nm_assert_not_reached (); + } + + nm_setting_ip_config_add_dns (s_ip, ns); + } + } +} + GHashTable * nmi_cmdline_reader_parse (const char *sysfs_dir, const char *const*argv) { @@ -855,7 +881,11 @@ nmi_cmdline_reader_parse (const char *sysfs_dir, const char *const*argv) gboolean ignore_bootif = FALSE; gboolean neednet = FALSE; gs_free char *bootif_val = NULL; + gs_free char *bootdev = NULL; gboolean net_ifnames = TRUE; + gs_unref_ptrarray GPtrArray *nameservers = NULL; + gs_unref_ptrarray GPtrArray *routes = NULL; + gboolean ignore_auto_dns = FALSE; int i; reader = reader_new (); @@ -870,6 +900,7 @@ nmi_cmdline_reader_parse (const char *sysfs_dir, const char *const*argv) for (i = 0; argv[i]; i++) { gs_free char *argument_clone = NULL; char *argument; + char *word; argument_clone = g_strdup (argv[i]); argument = argument_clone; @@ -877,9 +908,11 @@ nmi_cmdline_reader_parse (const char *sysfs_dir, const char *const*argv) tag = get_word (&argument, '='); if (strcmp (tag, "ip") == 0) parse_ip (reader, sysfs_dir, argument); - else if (strcmp (tag, "rd.route") == 0) - parse_rd_route (reader, argument); - else if (strcmp (tag, "bridge") == 0) + else if (strcmp (tag, "rd.route") == 0) { + 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) parse_master (reader, argument, NM_SETTING_BRIDGE_SETTING_NAME, "br"); else if (strcmp (tag, "bond") == 0) parse_master (reader, argument, NM_SETTING_BOND_SETTING_NAME, NULL); @@ -887,12 +920,20 @@ nmi_cmdline_reader_parse (const char *sysfs_dir, const char *const*argv) parse_master (reader, argument, NM_SETTING_TEAM_SETTING_NAME, NULL); else if (strcmp (tag, "vlan") == 0) parse_vlan (reader, argument); - else if (strcmp (tag, "bootdev") == 0) - parse_bootdev (reader, argument); - else if (strcmp (tag, "nameserver") == 0) - parse_nameserver (reader, argument); - else if (strcmp (tag, "rd.peerdns") == 0) - parse_rd_peerdns (reader, argument); + else if (strcmp (tag, "bootdev") == 0) { + g_free (bootdev); + bootdev = g_strdup (argument); + } else if (strcmp (tag, "nameserver") == 0) { + word = get_word (&argument, '\0'); + if (word) { + if (!nameservers) + nameservers = g_ptr_array_new_with_free_func (g_free); + g_ptr_array_add (nameservers, g_strdup (word)); + } + 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)) read_all_connections_from_fw (reader, sysfs_dir); else if (strcmp (tag, "rd.bootif") == 0) @@ -924,7 +965,10 @@ nmi_cmdline_reader_parse (const char *sysfs_dir, const char *const*argv) bootif += 3; } - connection = get_connection (reader, NULL, NM_SETTING_WIRED_SETTING_NAME); + connection = get_connection (reader, NULL, NM_SETTING_WIRED_SETTING_NAME, FALSE); + if (!connection) + connection = get_default_connection (reader); + s_wired = nm_connection_get_setting_wired (connection); if ( nm_connection_get_interface_name (connection) @@ -942,11 +986,28 @@ nmi_cmdline_reader_parse (const char *sysfs_dir, const char *const*argv) NM_SETTING_WIRED_MAC_ADDRESS, bootif, NULL); } + + if (bootdev) { + NMConnection *connection; + + connection = get_connection (reader, bootdev, NULL, TRUE); + reader->bootdev_connection = connection; + } + if (neednet && g_hash_table_size (reader->hash) == 0) { /* Make sure there's some connection. */ - get_connection (reader, NULL, NM_SETTING_WIRED_SETTING_NAME); + get_default_connection (reader); } + if (routes) + add_routes (reader, routes); + + if (nameservers) + add_nameservers (reader, nameservers); + + if (ignore_auto_dns) + set_ignore_auto_dns (reader); + g_hash_table_foreach (reader->hash, _normalize_conn, NULL); return reader_destroy (reader, FALSE); } diff --git a/src/initrd/tests/test-cmdline-reader.c b/src/initrd/tests/test-cmdline-reader.c index 6725e2c995..b2b06e27c3 100644 --- a/src/initrd/tests/test-cmdline-reader.c +++ b/src/initrd/tests/test-cmdline-reader.c @@ -264,7 +264,7 @@ test_if_ip6_manual (void) } static void -test_multiple (void) +test_multiple_merge (void) { gs_unref_hashtable GHashTable *connections = NULL; const char *const*ARGV = NM_MAKE_STRV ("ip=192.0.2.2:::::eth0", @@ -306,6 +306,37 @@ test_multiple (void) g_assert_cmpstr (nm_ip_address_get_address (ip_addr), ==, "2001:db8::2"); } +static void +test_multiple_bootdev (void) +{ + gs_unref_hashtable GHashTable *connections = NULL; + const char *const*ARGV = NM_MAKE_STRV ("nameserver=1.2.3.4", + "ip=eth3:auto6", + "ip=eth4:dhcp", + "bootdev=eth4"); + NMConnection *connection; + NMSettingIPConfig *s_ip4; + NMSettingIPConfig *s_ip6; + + connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV); + g_assert (connections); + g_assert_cmpint (g_hash_table_size (connections), ==, 2); + + connection = g_hash_table_lookup (connections, "eth3"); + g_assert (connection); + s_ip6 = nm_connection_get_setting_ip6_config (connection); + g_assert (s_ip6); + g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_AUTO); + + connection = g_hash_table_lookup (connections, "eth4"); + g_assert (connection); + s_ip4 = nm_connection_get_setting_ip4_config (connection); + g_assert (s_ip4); + g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO); + g_assert_cmpint (nm_setting_ip_config_get_num_dns (s_ip4), ==, 1); + g_assert_cmpstr (nm_setting_ip_config_get_dns (s_ip4, 0), ==, "1.2.3.4"); +} + static void test_bootdev (void) { @@ -358,16 +389,16 @@ test_some_more (void) g_assert (connections); g_assert_cmpint (g_hash_table_size (connections), ==, 2); - connection = g_hash_table_lookup (connections, "default_connection"); + connection = g_hash_table_lookup (connections, "eth1"); g_assert (connection); nmtst_assert_connection_verifies_without_normalization (connection); s_con = nm_connection_get_setting_connection (connection); g_assert (s_con); g_assert_cmpstr (nm_setting_connection_get_connection_type (s_con), ==, NM_SETTING_WIRED_SETTING_NAME); - g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "Wired Connection"); + g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "eth1"); g_assert_cmpstr (nm_setting_connection_get_interface_name (s_con), ==, "eth1"); - g_assert_cmpint (nm_setting_connection_get_multi_connect (s_con), ==, NM_CONNECTION_MULTI_CONNECT_MULTIPLE); + g_assert_cmpint (nm_setting_connection_get_multi_connect (s_con), ==, NM_CONNECTION_MULTI_CONNECT_SINGLE); s_wired = nm_connection_get_setting_wired (connection); g_assert (s_wired); @@ -409,7 +440,8 @@ test_some_more (void) s_ip6 = nm_connection_get_setting_ip6_config (connection); g_assert (s_ip6); g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_AUTO); - g_assert_cmpint (nm_setting_ip_config_get_num_dns (s_ip6), ==, 0); + g_assert_cmpint (nm_setting_ip_config_get_num_dns (s_ip6), ==, 1); + g_assert_cmpstr (nm_setting_ip_config_get_dns (s_ip6, 0), ==, "2001:db8:3::53"); g_assert_cmpint (nm_setting_ip_config_get_num_routes (s_ip6), ==, 1); g_assert (!nm_setting_ip_config_get_gateway (s_ip6)); ip_route = nm_setting_ip_config_get_route (s_ip6, 0); @@ -1052,6 +1084,57 @@ test_bootif_hwtype (void) g_assert (nm_setting_ip_config_get_may_fail (s_ip6)); } +/* Check that nameservers are assigned to all existing + * connections that support the specific IPv4/IPv6 address + * family. + */ +static void +test_nameserver (void) +{ + gs_unref_hashtable GHashTable *connections = NULL; + const char *const*ARGV = NM_MAKE_STRV ("nameserver=1.1.1.1", + "ip=eth0:dhcp", + "ip=eth1:auto6", + "ip=10.11.12.13::10.11.12.1:24:foo.example.com:eth2:none", + "nameserver=1.0.0.1", + "nameserver=[2606:4700:4700::1111]"); + NMConnection *connection; + NMSettingIPConfig *s_ip; + + connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV); + g_assert (connections); + g_assert_cmpint (g_hash_table_size (connections), ==, 3); + + connection = g_hash_table_lookup (connections, "eth0"); + g_assert (connection); + nmtst_assert_connection_verifies_without_normalization (connection); + + s_ip = nm_connection_get_setting_ip4_config (connection); + g_assert (s_ip); + g_assert_cmpint (nm_setting_ip_config_get_num_dns (s_ip), ==, 2); + g_assert_cmpstr (nm_setting_ip_config_get_dns (s_ip, 0), ==, "1.1.1.1"); + g_assert_cmpstr (nm_setting_ip_config_get_dns (s_ip, 1), ==, "1.0.0.1"); + + connection = g_hash_table_lookup (connections, "eth1"); + g_assert (connection); + nmtst_assert_connection_verifies_without_normalization (connection); + + s_ip = nm_connection_get_setting_ip6_config (connection); + g_assert (s_ip); + g_assert_cmpint (nm_setting_ip_config_get_num_dns (s_ip), ==, 1); + g_assert_cmpstr (nm_setting_ip_config_get_dns (s_ip, 0), ==, "2606:4700:4700::1111"); + + connection = g_hash_table_lookup (connections, "eth2"); + g_assert (connection); + nmtst_assert_connection_verifies_without_normalization (connection); + + s_ip = nm_connection_get_setting_ip4_config (connection); + g_assert (s_ip); + g_assert_cmpint (nm_setting_ip_config_get_num_dns (s_ip), ==, 2); + g_assert_cmpstr (nm_setting_ip_config_get_dns (s_ip, 0), ==, "1.1.1.1"); + g_assert_cmpstr (nm_setting_ip_config_get_dns (s_ip, 1), ==, "1.0.0.1"); +} + static void test_bootif_off (void) { @@ -1075,7 +1158,9 @@ int main (int argc, char **argv) g_test_add_func ("/initrd/cmdline/if_auto_with_mtu_and_mac", test_if_auto_with_mtu_and_mac); g_test_add_func ("/initrd/cmdline/if_ip4_manual", test_if_ip4_manual); g_test_add_func ("/initrd/cmdline/if_ip6_manual", test_if_ip6_manual); - g_test_add_func ("/initrd/cmdline/multiple", test_multiple); + g_test_add_func ("/initrd/cmdline/multiple/merge", test_multiple_merge); + g_test_add_func ("/initrd/cmdline/multiple/bootdev", test_multiple_bootdev); + g_test_add_func ("/initrd/cmdline/nameserver", test_nameserver); g_test_add_func ("/initrd/cmdline/some_more", test_some_more); g_test_add_func ("/initrd/cmdline/bootdev", test_bootdev); g_test_add_func ("/initrd/cmdline/bond", test_bond); From 99e01888864ddba4eda31c43809842afa2594a56 Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Wed, 25 Mar 2020 10:17:03 +0100 Subject: [PATCH 7/7] initrd: add 'reader_' prefix to functions acting on Reader --- src/initrd/nmi-cmdline-reader.c | 133 ++++++++++++++++---------------- 1 file changed, 68 insertions(+), 65 deletions(-) diff --git a/src/initrd/nmi-cmdline-reader.c b/src/initrd/nmi-cmdline-reader.c index 49b5126b6e..1c824dda6a 100644 --- a/src/initrd/nmi-cmdline-reader.c +++ b/src/initrd/nmi-cmdline-reader.c @@ -52,7 +52,7 @@ reader_destroy (Reader *reader, gboolean free_hash) } static NMConnection * -add_connection (Reader *reader, const char *name, NMConnection *connection_take) +reader_add_connection (Reader *reader, const char *name, NMConnection *connection_take) { char *name_dup; @@ -65,19 +65,19 @@ add_connection (Reader *reader, const char *name, NMConnection *connection_take) /* Returns a new connection owned by the reader */ static NMConnection * -create_connection (Reader *reader, - const char *basename, - const char *id, - const char *ifname, - const char *type_name, - NMConnectionMultiConnect multi_connect) +reader_create_connection (Reader *reader, + const char *basename, + const char *id, + const char *ifname, + const char *type_name, + NMConnectionMultiConnect multi_connect) { NMConnection *connection; NMSetting *setting; - connection = add_connection (reader, - basename, - nm_simple_connection_new ()); + connection = reader_add_connection (reader, + basename, + nm_simple_connection_new ()); /* Start off assuming dynamic IP configurations. */ @@ -110,27 +110,27 @@ create_connection (Reader *reader, } static NMConnection * -get_default_connection (Reader *reader) +reader_get_default_connection (Reader *reader) { NMConnection *con; if (!reader->default_connection) { - con = create_connection (reader, - "default_connection", - "Wired Connection", - NULL, - NM_SETTING_WIRED_SETTING_NAME, - NM_CONNECTION_MULTI_CONNECT_MULTIPLE); + con = reader_create_connection (reader, + "default_connection", + "Wired Connection", + NULL, + NM_SETTING_WIRED_SETTING_NAME, + NM_CONNECTION_MULTI_CONNECT_MULTIPLE); reader->default_connection = con; } return reader->default_connection; } static NMConnection * -get_connection (Reader *reader, - const char *ifname, - const char *type_name, - gboolean create_if_missing) +reader_get_connection (Reader *reader, + const char *ifname, + const char *type_name, + gboolean create_if_missing) { NMConnection *connection = NULL; NMSetting *setting; @@ -172,10 +172,10 @@ get_connection (Reader *reader, if (!type_name) type_name = NM_SETTING_WIRED_SETTING_NAME; - connection = create_connection (reader, ifname, - ifname ?: "Wired Connection", - ifname, type_name, - NM_CONNECTION_MULTI_CONNECT_SINGLE); + connection = reader_create_connection (reader, ifname, + ifname ?: "Wired Connection", + ifname, type_name, + NM_CONNECTION_MULTI_CONNECT_SINGLE); } setting = (NMSetting *) nm_connection_get_setting_connection (connection); @@ -259,7 +259,7 @@ _base_setting_set (NMConnection *connection, const char *property, const char *v } static void -read_all_connections_from_fw (Reader *reader, const char *sysfs_dir) +reader_read_all_connections_from_fw (Reader *reader, const char *sysfs_dir) { gs_unref_hashtable GHashTable *ibft = NULL; NMConnection *dt_connection; @@ -293,16 +293,16 @@ read_all_connections_from_fw (Reader *reader, const char *sysfs_dir) } name = g_strdup_printf ("ibft%s", index); - add_connection (reader, name, g_steal_pointer (&connection)); + reader_add_connection (reader, name, g_steal_pointer (&connection)); } dt_connection = nmi_dt_reader_parse (sysfs_dir); if (dt_connection) - add_connection (reader, "ofw", dt_connection); + reader_add_connection (reader, "ofw", dt_connection); } static void -parse_ip (Reader *reader, const char *sysfs_dir, char *argument) +reader_parse_ip (Reader *reader, const char *sysfs_dir, char *argument) { NMConnection *connection; NMSettingIPConfig *s_ip4 = NULL, *s_ip6 = NULL; @@ -365,15 +365,15 @@ parse_ip (Reader *reader, const char *sysfs_dir, char *argument) if (ifname == NULL && ( g_strcmp0 (kind, "fw") == 0 || g_strcmp0 (kind, "ibft") == 0)) { - read_all_connections_from_fw (reader, sysfs_dir); + reader_read_all_connections_from_fw (reader, sysfs_dir); return; } /* Parsing done, construct the NMConnection. */ if (ifname) - connection = get_connection (reader, ifname, NULL, TRUE); + connection = reader_get_connection (reader, ifname, NULL, TRUE); else - connection = get_default_connection (reader); + connection = reader_get_default_connection (reader); s_ip4 = nm_connection_get_setting_ip4_config (connection); s_ip6 = nm_connection_get_setting_ip6_config (connection); @@ -565,10 +565,10 @@ parse_ip (Reader *reader, const char *sysfs_dir, char *argument) } static void -parse_master (Reader *reader, - char *argument, - const char *type_name, - const char *default_name) +reader_parse_master (Reader *reader, + char *argument, + const char *type_name, + const char *default_name) { NMConnection *connection; NMSettingConnection *s_con; @@ -587,7 +587,7 @@ parse_master (Reader *reader, master = master_to_free = g_strdup_printf ("%s0", default_name ?: type_name); slaves = get_word (&argument, ':'); - connection = get_connection (reader, master, type_name, TRUE); + connection = reader_get_connection (reader, master, type_name, TRUE); s_con = nm_connection_get_setting_connection (connection); master = nm_setting_connection_get_uuid (s_con); @@ -609,7 +609,7 @@ parse_master (Reader *reader, if (slave == NULL) slave = "eth0"; - connection = get_connection (reader, slave, NULL, TRUE); + connection = reader_get_connection (reader, slave, NULL, TRUE); s_con = nm_connection_get_setting_connection (connection); g_object_set (s_con, NM_SETTING_CONNECTION_SLAVE_TYPE, type_name, @@ -624,7 +624,7 @@ parse_master (Reader *reader, } static void -add_routes (Reader *reader, GPtrArray *array) +reader_add_routes (Reader *reader, GPtrArray *array) { guint i; @@ -648,13 +648,13 @@ add_routes (Reader *reader, GPtrArray *array) interface = get_word (&argument, ':'); if (interface) - connection = get_connection (reader, interface, NULL, TRUE); + connection = reader_get_connection (reader, interface, NULL, TRUE); if (!connection) connection = reader->bootdev_connection; if (!connection) - connection = get_connection (reader, interface, NULL, FALSE); + connection = reader_get_connection (reader, interface, NULL, FALSE); if (!connection) - connection = get_default_connection (reader); + connection = reader_get_default_connection (reader); if (net && *net) { if (!nm_utils_parse_inaddr_prefix_bin (family, net, &family, &net_addr, &net_prefix)) { @@ -698,7 +698,7 @@ add_routes (Reader *reader, GPtrArray *array) } static void -parse_vlan (Reader *reader, char *argument) +reader_parse_vlan (Reader *reader, char *argument) { NMConnection *connection; NMSettingVlan *s_vlan; @@ -714,7 +714,7 @@ parse_vlan (Reader *reader, char *argument) break; } - connection = get_connection (reader, vlan, NM_SETTING_VLAN_SETTING_NAME, TRUE); + connection = reader_get_connection (reader, vlan, NM_SETTING_VLAN_SETTING_NAME, TRUE); s_vlan = nm_connection_get_setting_vlan (connection); g_object_set (s_vlan, @@ -727,7 +727,7 @@ parse_vlan (Reader *reader, char *argument) } static void -parse_rd_znet (Reader *reader, char *argument, gboolean net_ifnames) +reader_parse_rd_znet (Reader *reader, char *argument, gboolean net_ifnames) { const char *nettype; const char *subchannels[4] = { 0, 0, 0, 0 }; @@ -777,7 +777,7 @@ parse_rd_znet (Reader *reader, char *argument, gboolean net_ifnames) ifname = g_strdup_printf ("%s%d", prefix, index); } - connection = get_connection (reader, ifname, NM_SETTING_WIRED_SETTING_NAME, TRUE); + connection = reader_get_connection (reader, ifname, NM_SETTING_WIRED_SETTING_NAME, TRUE); s_wired = nm_connection_get_setting_wired (connection); g_object_set (s_wired, NM_SETTING_WIRED_S390_NETTYPE, nettype, @@ -808,7 +808,7 @@ _normalize_conn (gpointer key, gpointer value, gpointer user_data) } static void -set_ignore_auto_dns (Reader *reader) +reader_set_ignore_auto_dns (Reader *reader) { GHashTableIter iter; NMConnection *connection; @@ -829,7 +829,7 @@ set_ignore_auto_dns (Reader *reader) } static void -add_nameservers (Reader *reader, GPtrArray *nameservers) +reader_add_nameservers (Reader *reader, GPtrArray *nameservers) { NMConnection *connection; NMSettingIPConfig *s_ip; @@ -907,19 +907,19 @@ nmi_cmdline_reader_parse (const char *sysfs_dir, const char *const*argv) tag = get_word (&argument, '='); if (strcmp (tag, "ip") == 0) - parse_ip (reader, sysfs_dir, argument); + reader_parse_ip (reader, sysfs_dir, argument); else if (strcmp (tag, "rd.route") == 0) { 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) - parse_master (reader, argument, NM_SETTING_BRIDGE_SETTING_NAME, "br"); + reader_parse_master (reader, argument, NM_SETTING_BRIDGE_SETTING_NAME, "br"); else if (strcmp (tag, "bond") == 0) - parse_master (reader, argument, NM_SETTING_BOND_SETTING_NAME, NULL); + reader_parse_master (reader, argument, NM_SETTING_BOND_SETTING_NAME, NULL); else if (strcmp (tag, "team") == 0) - parse_master (reader, argument, NM_SETTING_TEAM_SETTING_NAME, NULL); + reader_parse_master (reader, argument, NM_SETTING_TEAM_SETTING_NAME, NULL); else if (strcmp (tag, "vlan") == 0) - parse_vlan (reader, argument); + reader_parse_vlan (reader, argument); else if (strcmp (tag, "bootdev") == 0) { g_free (bootdev); bootdev = g_strdup (argument); @@ -935,13 +935,13 @@ nmi_cmdline_reader_parse (const char *sysfs_dir, const char *const*argv) } 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)) - read_all_connections_from_fw (reader, sysfs_dir); + reader_read_all_connections_from_fw (reader, sysfs_dir); else if (strcmp (tag, "rd.bootif") == 0) ignore_bootif = !_nm_utils_ascii_str_to_bool (argument, TRUE); else if (strcmp (tag, "rd.neednet") == 0) neednet = _nm_utils_ascii_str_to_bool (argument, TRUE); else if (strcmp (tag, "rd.znet") == 0) - parse_rd_znet (reader, argument, net_ifnames); + reader_parse_rd_znet (reader, argument, net_ifnames); else if (g_ascii_strcasecmp (tag, "BOOTIF") == 0) { nm_clear_g_free (&bootif_val); bootif_val = g_strdup (argument); @@ -965,9 +965,9 @@ nmi_cmdline_reader_parse (const char *sysfs_dir, const char *const*argv) bootif += 3; } - connection = get_connection (reader, NULL, NM_SETTING_WIRED_SETTING_NAME, FALSE); + connection = reader_get_connection (reader, NULL, NM_SETTING_WIRED_SETTING_NAME, FALSE); if (!connection) - connection = get_default_connection (reader); + connection = reader_get_default_connection (reader); s_wired = nm_connection_get_setting_wired (connection); @@ -975,9 +975,12 @@ nmi_cmdline_reader_parse (const char *sysfs_dir, const char *const*argv) || ( nm_setting_wired_get_mac_address (s_wired) && !nm_utils_hwaddr_matches (nm_setting_wired_get_mac_address (s_wired), -1, bootif, -1))) { - connection = create_connection (reader, "bootif_connection", "BOOTIF Connection", - NULL, NM_SETTING_WIRED_SETTING_NAME, - NM_CONNECTION_MULTI_CONNECT_SINGLE); + connection = reader_create_connection (reader, + "bootif_connection", + "BOOTIF Connection", + NULL, + NM_SETTING_WIRED_SETTING_NAME, + NM_CONNECTION_MULTI_CONNECT_SINGLE); s_wired = (NMSettingWired *) nm_setting_wired_new (); nm_connection_add_setting (connection, (NMSetting *) s_wired); } @@ -990,23 +993,23 @@ nmi_cmdline_reader_parse (const char *sysfs_dir, const char *const*argv) if (bootdev) { NMConnection *connection; - connection = get_connection (reader, bootdev, NULL, TRUE); + connection = reader_get_connection (reader, bootdev, NULL, TRUE); reader->bootdev_connection = connection; } if (neednet && g_hash_table_size (reader->hash) == 0) { /* Make sure there's some connection. */ - get_default_connection (reader); + reader_get_default_connection (reader); } if (routes) - add_routes (reader, routes); + reader_add_routes (reader, routes); if (nameservers) - add_nameservers (reader, nameservers); + reader_add_nameservers (reader, nameservers); if (ignore_auto_dns) - set_ignore_auto_dns (reader); + reader_set_ignore_auto_dns (reader); g_hash_table_foreach (reader->hash, _normalize_conn, NULL); return reader_destroy (reader, FALSE);