initrd: fix parsing of ip= arguments with empty first token
The parser checks if the first token of an ip= argument is an IP address to determine which of the two possible syntaxes is used: ip=<interface>:{dhcp|on|any|dhcp6|auto6}[:[<mtu>][:<macaddr>]] ip=<client-IP>:[<peer>]:<gateway-IP>:<netmask>:<client_hostname>:<interface>:{none|off|dhcp|on|any|dhcp6|auto6|ibft}[:[<mtu>][:<macaddr>]] This works as long as the first token is not empty, which - according to the dracut.cmdline man page - seems to be guaranteed. However, the network-legacy dracut plugin accepts an empty interface or client IP. Also, if a user needs DHCP and wants to specify a hostname, the only possible syntax is: ip=::::<hostname>::dhcp Change the parser to check the second token instead, similarly to what the network-legacy module does [1]. [1] https://github.com/dracutdevs/dracut/blob/050/modules.d/40network/net-lib.sh#L490 https://bugzilla.redhat.com/show_bug.cgi?id=1900260 https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/693
This commit is contained in:
@@ -390,6 +390,7 @@ reader_parse_ip(Reader *reader, const char *sysfs_dir, char *argument)
|
|||||||
NMSettingIPConfig *s_ip4 = NULL, *s_ip6 = NULL;
|
NMSettingIPConfig *s_ip4 = NULL, *s_ip6 = NULL;
|
||||||
gs_unref_hashtable GHashTable *ibft = NULL;
|
gs_unref_hashtable GHashTable *ibft = NULL;
|
||||||
const char * tmp;
|
const char * tmp;
|
||||||
|
const char * tmp2;
|
||||||
const char * kind = NULL;
|
const char * kind = NULL;
|
||||||
const char * client_ip = NULL;
|
const char * client_ip = NULL;
|
||||||
const char * peer = NULL;
|
const char * peer = NULL;
|
||||||
@@ -418,17 +419,37 @@ reader_parse_ip(Reader *reader, const char *sysfs_dir, char *argument)
|
|||||||
/* ip={dhcp|on|any|dhcp6|auto6|ibft} */
|
/* ip={dhcp|on|any|dhcp6|auto6|ibft} */
|
||||||
kind = tmp;
|
kind = tmp;
|
||||||
} else {
|
} else {
|
||||||
client_ip_family = get_ip_address_family(tmp, TRUE);
|
tmp2 = get_word(&argument, ':');
|
||||||
if (client_ip_family != AF_UNSPEC) {
|
if (NM_IN_STRSET(tmp2,
|
||||||
/* <client-IP>:[<peer>]:<gateway-IP>:<netmask>:<client_hostname>: */
|
"none",
|
||||||
|
"off",
|
||||||
|
"dhcp",
|
||||||
|
"on"
|
||||||
|
"any",
|
||||||
|
"dhcp6",
|
||||||
|
"auto",
|
||||||
|
"auto6",
|
||||||
|
"ibft")) {
|
||||||
|
/* <ifname>:{none|off|dhcp|on|any|dhcp6|auto|auto6|ibft} */
|
||||||
|
iface_spec = tmp;
|
||||||
|
kind = tmp2;
|
||||||
|
} else {
|
||||||
|
/* <client-IP>:[<peer>]:<gateway-IP>:<netmask>:<client_hostname>:<kind> */
|
||||||
client_ip = tmp;
|
client_ip = tmp;
|
||||||
peer = get_word(&argument, ':');
|
if (client_ip) {
|
||||||
|
client_ip_family = get_ip_address_family(client_ip, TRUE);
|
||||||
|
if (client_ip_family == AF_UNSPEC) {
|
||||||
|
_LOGW(LOGD_CORE, "Invalid IP address '%s'.", client_ip);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
peer = tmp2;
|
||||||
gateway_ip = get_word(&argument, ':');
|
gateway_ip = get_word(&argument, ':');
|
||||||
netmask = get_word(&argument, ':');
|
netmask = get_word(&argument, ':');
|
||||||
client_hostname = get_word(&argument, ':');
|
client_hostname = get_word(&argument, ':');
|
||||||
iface_spec = get_word(&argument, ':');
|
iface_spec = get_word(&argument, ':');
|
||||||
} else {
|
kind = get_word(&argument, ':');
|
||||||
iface_spec = tmp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (client_hostname && !nm_sd_hostname_is_valid(client_hostname, FALSE))
|
if (client_hostname && !nm_sd_hostname_is_valid(client_hostname, FALSE))
|
||||||
@@ -439,10 +460,6 @@ reader_parse_ip(Reader *reader, const char *sysfs_dir, char *argument)
|
|||||||
reader->hostname = g_strdup(client_hostname);
|
reader->hostname = g_strdup(client_hostname);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* <ifname>:{none|off|dhcp|on|any|dhcp6|auto6|ibft} */
|
|
||||||
|
|
||||||
kind = get_word(&argument, ':');
|
|
||||||
|
|
||||||
tmp = get_word(&argument, ':');
|
tmp = get_word(&argument, ':');
|
||||||
dns_addr_family[0] = get_ip_address_family(tmp, FALSE);
|
dns_addr_family[0] = get_ip_address_family(tmp, FALSE);
|
||||||
if (dns_addr_family[0] != AF_UNSPEC) {
|
if (dns_addr_family[0] != AF_UNSPEC) {
|
||||||
|
@@ -79,6 +79,116 @@ test_auto(void)
|
|||||||
g_assert(!nm_setting_ip_config_get_gateway(s_ip6));
|
g_assert(!nm_setting_ip_config_get_gateway(s_ip6));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_dhcp_with_hostname(void)
|
||||||
|
{
|
||||||
|
gs_unref_hashtable GHashTable *connections = NULL;
|
||||||
|
const char *const * ARGV = NM_MAKE_STRV("ip=::::host1::dhcp");
|
||||||
|
NMConnection * connection;
|
||||||
|
NMSettingConnection * s_con;
|
||||||
|
NMSettingWired * s_wired;
|
||||||
|
NMSettingIPConfig * s_ip4;
|
||||||
|
NMSettingIPConfig * s_ip6;
|
||||||
|
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), ==, 1);
|
||||||
|
g_assert_cmpstr(hostname, ==, "host1");
|
||||||
|
|
||||||
|
connection = g_hash_table_lookup(connections, "default_connection");
|
||||||
|
g_assert(connection);
|
||||||
|
nmtst_assert_connection_verifies_without_normalization(connection);
|
||||||
|
|
||||||
|
g_assert(!nm_connection_get_setting_vlan(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_cmpint(nm_setting_connection_get_timestamp(s_con), ==, 0);
|
||||||
|
g_assert_cmpint(nm_setting_connection_get_multi_connect(s_con),
|
||||||
|
==,
|
||||||
|
NM_CONNECTION_MULTI_CONNECT_MULTIPLE);
|
||||||
|
g_assert_cmpint(nm_setting_connection_get_wait_device_timeout(s_con), ==, -1);
|
||||||
|
|
||||||
|
g_assert(nm_setting_connection_get_autoconnect(s_con));
|
||||||
|
|
||||||
|
s_wired = nm_connection_get_setting_wired(connection);
|
||||||
|
g_assert(s_wired);
|
||||||
|
g_assert(!nm_setting_wired_get_mac_address(s_wired));
|
||||||
|
g_assert_cmpint(nm_setting_wired_get_mtu(s_wired), ==, 0);
|
||||||
|
|
||||||
|
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_dhcp_with_mtu(void)
|
||||||
|
{
|
||||||
|
const char *const *ARGV0 = NM_MAKE_STRV("ip=:dhcp:1499");
|
||||||
|
const char *const *ARGV1 = NM_MAKE_STRV("ip=::::::dhcp:1499");
|
||||||
|
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;
|
||||||
|
NMSettingConnection * s_con;
|
||||||
|
NMSettingWired * s_wired;
|
||||||
|
NMSettingIPConfig * s_ip4;
|
||||||
|
NMSettingIPConfig * s_ip6;
|
||||||
|
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, "default_connection");
|
||||||
|
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_cmpint(nm_setting_connection_get_timestamp(s_con), ==, 0);
|
||||||
|
g_assert_cmpint(nm_setting_connection_get_multi_connect(s_con),
|
||||||
|
==,
|
||||||
|
NM_CONNECTION_MULTI_CONNECT_MULTIPLE);
|
||||||
|
g_assert_cmpint(nm_setting_connection_get_wait_device_timeout(s_con), ==, -1);
|
||||||
|
|
||||||
|
g_assert(nm_setting_connection_get_autoconnect(s_con));
|
||||||
|
|
||||||
|
s_wired = nm_connection_get_setting_wired(connection);
|
||||||
|
g_assert(s_wired);
|
||||||
|
g_assert(!nm_setting_wired_get_mac_address(s_wired));
|
||||||
|
g_assert_cmpint(nm_setting_wired_get_mtu(s_wired), ==, 1499);
|
||||||
|
|
||||||
|
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
|
static void
|
||||||
test_if_auto_with_mtu(void)
|
test_if_auto_with_mtu(void)
|
||||||
{
|
{
|
||||||
@@ -2071,6 +2181,8 @@ main(int argc, char **argv)
|
|||||||
nmtst_init_assert_logging(&argc, &argv, "INFO", "DEFAULT");
|
nmtst_init_assert_logging(&argc, &argv, "INFO", "DEFAULT");
|
||||||
|
|
||||||
g_test_add_func("/initrd/cmdline/auto", test_auto);
|
g_test_add_func("/initrd/cmdline/auto", test_auto);
|
||||||
|
g_test_add_func("/initrd/cmdline/dhcp_with_hostname", test_dhcp_with_hostname);
|
||||||
|
g_test_add_func("/initrd/cmdline/dhcp_with_mtu", test_dhcp_with_mtu);
|
||||||
g_test_add_func("/initrd/cmdline/if_auto_with_mtu", test_if_auto_with_mtu);
|
g_test_add_func("/initrd/cmdline/if_auto_with_mtu", test_if_auto_with_mtu);
|
||||||
g_test_add_func("/initrd/cmdline/if_dhcp6", test_if_dhcp6);
|
g_test_add_func("/initrd/cmdline/if_dhcp6", test_if_dhcp6);
|
||||||
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_auto_with_mtu_and_mac", test_if_auto_with_mtu_and_mac);
|
||||||
|
Reference in New Issue
Block a user