diff --git a/src/initrd/nm-initrd-generator.h b/src/initrd/nm-initrd-generator.h index cac01cb861..69c24b1b0b 100644 --- a/src/initrd/nm-initrd-generator.h +++ b/src/initrd/nm-initrd-generator.h @@ -11,17 +11,23 @@ #define NMI_WAIT_DEVICE_TIMEOUT_MS 60000 -static inline gboolean -guess_ip_address_family(const char *str) +static inline int +get_ip_address_family(const char *str, gboolean with_prefix) { - if (str == NULL) - return AF_UNSPEC; - else if (strchr(str, '.')) - return AF_INET; - else if (strchr(str, ':')) - return AF_INET6; - else + int addr_family; + + if (!str) return AF_UNSPEC; + + if (with_prefix) { + if (nm_utils_parse_inaddr_prefix_bin(AF_UNSPEC, str, &addr_family, NULL, NULL)) + return addr_family; + } else { + if (nm_utils_parse_inaddr_bin(AF_UNSPEC, str, &addr_family, NULL)) + return addr_family; + } + + return AF_UNSPEC; } GHashTable *nmi_ibft_read(const char *sysfs_dir); diff --git a/src/initrd/nmi-cmdline-reader.c b/src/initrd/nmi-cmdline-reader.c index b9432d4a62..9c5699afb8 100644 --- a/src/initrd/nmi-cmdline-reader.c +++ b/src/initrd/nmi-cmdline-reader.c @@ -411,7 +411,7 @@ reader_parse_ip(Reader *reader, const char *sysfs_dir, char *argument) /* ip={dhcp|on|any|dhcp6|auto6|ibft} */ kind = tmp; } else { - client_ip_family = guess_ip_address_family(tmp); + client_ip_family = get_ip_address_family(tmp, TRUE); if (client_ip_family != AF_UNSPEC) { /* :[]:::: */ client_ip = tmp; @@ -437,11 +437,11 @@ reader_parse_ip(Reader *reader, const char *sysfs_dir, char *argument) kind = get_word(&argument, ':'); tmp = get_word(&argument, ':'); - dns_addr_family[0] = guess_ip_address_family(tmp); + dns_addr_family[0] = get_ip_address_family(tmp, FALSE); if (dns_addr_family[0] != AF_UNSPEC) { dns[0] = tmp; dns[1] = get_word(&argument, ':'); - dns_addr_family[1] = guess_ip_address_family(dns[1]); + dns_addr_family[1] = get_ip_address_family(dns[1], FALSE); if (*argument) _LOGW(LOGD_CORE, "Ignoring extra: '%s'.", argument); } else { @@ -506,9 +506,8 @@ reader_parse_ip(Reader *reader, const char *sysfs_dir, char *argument) _LOGW(LOGD_CORE, "Invalid address '%s': %s", client_ip, error->message); g_clear_error(&error); } - } else { - _LOGW(LOGD_CORE, "Unrecognized address: %s", client_ip); - } + } else + nm_assert_not_reached(); if (address) { switch (client_ip_family) { @@ -531,7 +530,7 @@ reader_parse_ip(Reader *reader, const char *sysfs_dir, char *argument) nm_setting_ip_config_add_address(s_ip6, address); break; default: - _LOGW(LOGD_CORE, "Unknown address family: %s", client_ip); + nm_assert_not_reached(); break; } nm_ip_address_unref(address); @@ -618,22 +617,16 @@ reader_parse_ip(Reader *reader, const char *sysfs_dir, char *argument) _LOGW(LOGD_CORE, "Ignoring peer: %s (not implemented)\n", peer); if (gateway_ip && *gateway_ip) { - int addr_family = guess_ip_address_family(gateway_ip); - - if (nm_utils_ipaddr_is_valid(addr_family, gateway_ip)) { - switch (addr_family) { - case AF_INET: - g_object_set(s_ip4, NM_SETTING_IP_CONFIG_GATEWAY, gateway_ip, NULL); - break; - case AF_INET6: - g_object_set(s_ip6, NM_SETTING_IP_CONFIG_GATEWAY, gateway_ip, NULL); - break; - default: - _LOGW(LOGD_CORE, "Unknown address family: %s", gateway_ip); - break; - } - } else { + switch (get_ip_address_family(gateway_ip, FALSE)) { + case AF_INET: + g_object_set(s_ip4, NM_SETTING_IP_CONFIG_GATEWAY, gateway_ip, NULL); + break; + case AF_INET6: + g_object_set(s_ip6, NM_SETTING_IP_CONFIG_GATEWAY, gateway_ip, NULL); + break; + default: _LOGW(LOGD_CORE, "Invalid gateway: %s", gateway_ip); + break; } } @@ -941,7 +934,7 @@ reader_add_nameservers(Reader *reader, GPtrArray *nameservers) for (i = 0; i < nameservers->len; i++) { ns = nameservers->pdata[i]; - addr_family = guess_ip_address_family(ns); + addr_family = get_ip_address_family(ns, FALSE); if (addr_family == AF_UNSPEC) { _LOGW(LOGD_CORE, "Unknown address family: %s", ns); continue; diff --git a/src/initrd/nmi-ibft-reader.c b/src/initrd/nmi-ibft-reader.c index 80b2e5f9e9..b7ce467197 100644 --- a/src/initrd/nmi-ibft-reader.c +++ b/src/initrd/nmi-ibft-reader.c @@ -165,9 +165,9 @@ ip_setting_add_from_block(GHashTable *nic, NMConnection *connection, GError **er NULL); } - family = guess_ip_address_family(s_ipaddr); + family = get_ip_address_family(s_ipaddr, FALSE); if (family == AF_UNSPEC) - family = guess_ip_address_family(s_gateway); + family = get_ip_address_family(s_gateway, FALSE); switch (family) { case AF_INET: diff --git a/src/initrd/tests/test-cmdline-reader.c b/src/initrd/tests/test-cmdline-reader.c index c42d7f11a9..281d690dcd 100644 --- a/src/initrd/tests/test-cmdline-reader.c +++ b/src/initrd/tests/test-cmdline-reader.c @@ -1219,6 +1219,54 @@ test_team(void) NM_CONNECTION_MULTI_CONNECT_SINGLE); } +static void +test_vlan(void) +{ + const char *const *ARGV0 = NM_MAKE_STRV("ip=eth0.100:dhcp", "vlan=eth0.100:eth0"); + const char *const *ARGV1 = NM_MAKE_STRV("vlan=eth0.100:eth0", "ip=eth0.100:dhcp"); + const char *const *ARGV[] = {ARGV0, ARGV1}; + guint i; + + for (i = 0; i < G_N_ELEMENTS(ARGV); i++) { + gs_unref_hashtable GHashTable *connections = NULL; + NMConnection * connection; + NMSettingIPConfig * s_ip4; + NMSettingIPConfig * s_ip6; + NMSettingVlan * s_vlan; + gs_free char * hostname = NULL; + + connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV[i], &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.100"); + g_assert(connection); + nmtst_assert_connection_verifies_without_normalization(connection); + g_assert_cmpstr(nm_connection_get_connection_type(connection), + ==, + NM_SETTING_VLAN_SETTING_NAME); + g_assert_cmpstr(nm_connection_get_id(connection), ==, "eth0.100"); + + s_vlan = nm_connection_get_setting_vlan(connection); + g_assert(s_vlan); + g_assert_cmpstr(nm_setting_vlan_get_parent(s_vlan), ==, "eth0"); + g_assert_cmpint(nm_setting_vlan_get_id(s_vlan), ==, 100); + + 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); + + 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); + } +} + static void test_ibft_ip_dev(void) { @@ -1852,6 +1900,7 @@ main(int argc, char **argv) g_test_add_func("/initrd/cmdline/bond/ip", test_bond_ip); g_test_add_func("/initrd/cmdline/bond/default", test_bond_default); g_test_add_func("/initrd/cmdline/team", test_team); + g_test_add_func("/initrd/cmdline/vlan", test_vlan); g_test_add_func("/initrd/cmdline/bridge", test_bridge); g_test_add_func("/initrd/cmdline/bridge/default", test_bridge_default); g_test_add_func("/initrd/cmdline/bridge/ip", test_bridge_ip);