mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-05-08 19:28:04 +02:00
initrd: fix parsing of ip= argument with dotted interface name
The command line parser looks for a dot or a colon to determine
whether the first token in a ip= argument is a IPv4 address (dot), an
IPv6 address (colon) or an interface name (none). This strategy
doesn't work for interface names containing a dot (typically VLANs).
Instead, try to parse the IPv4/IPv6 address in the token; if this
fails then consider the token as an interface name.
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/issues/581
(cherry picked from commit 4aa902ecf5)
This commit is contained in:
parent
58a6697e96
commit
f766b3cbae
4 changed files with 82 additions and 34 deletions
|
|
@ -11,17 +11,23 @@
|
||||||
|
|
||||||
#define NMI_WAIT_DEVICE_TIMEOUT_MS 60000
|
#define NMI_WAIT_DEVICE_TIMEOUT_MS 60000
|
||||||
|
|
||||||
static inline gboolean
|
static inline int
|
||||||
guess_ip_address_family(const char *str)
|
get_ip_address_family(const char *str, gboolean with_prefix)
|
||||||
{
|
{
|
||||||
if (str == NULL)
|
int addr_family;
|
||||||
return AF_UNSPEC;
|
|
||||||
else if (strchr(str, '.'))
|
if (!str)
|
||||||
return AF_INET;
|
|
||||||
else if (strchr(str, ':'))
|
|
||||||
return AF_INET6;
|
|
||||||
else
|
|
||||||
return AF_UNSPEC;
|
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);
|
GHashTable *nmi_ibft_read(const char *sysfs_dir);
|
||||||
|
|
|
||||||
|
|
@ -411,7 +411,7 @@ 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 = guess_ip_address_family(tmp);
|
client_ip_family = get_ip_address_family(tmp, TRUE);
|
||||||
if (client_ip_family != AF_UNSPEC) {
|
if (client_ip_family != AF_UNSPEC) {
|
||||||
/* <client-IP>:[<peer>]:<gateway-IP>:<netmask>:<client_hostname>: */
|
/* <client-IP>:[<peer>]:<gateway-IP>:<netmask>:<client_hostname>: */
|
||||||
client_ip = tmp;
|
client_ip = tmp;
|
||||||
|
|
@ -437,11 +437,11 @@ reader_parse_ip(Reader *reader, const char *sysfs_dir, char *argument)
|
||||||
kind = get_word(&argument, ':');
|
kind = get_word(&argument, ':');
|
||||||
|
|
||||||
tmp = 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) {
|
if (dns_addr_family[0] != AF_UNSPEC) {
|
||||||
dns[0] = tmp;
|
dns[0] = tmp;
|
||||||
dns[1] = get_word(&argument, ':');
|
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)
|
if (*argument)
|
||||||
_LOGW(LOGD_CORE, "Ignoring extra: '%s'.", argument);
|
_LOGW(LOGD_CORE, "Ignoring extra: '%s'.", argument);
|
||||||
} else {
|
} 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);
|
_LOGW(LOGD_CORE, "Invalid address '%s': %s", client_ip, error->message);
|
||||||
g_clear_error(&error);
|
g_clear_error(&error);
|
||||||
}
|
}
|
||||||
} else {
|
} else
|
||||||
_LOGW(LOGD_CORE, "Unrecognized address: %s", client_ip);
|
nm_assert_not_reached();
|
||||||
}
|
|
||||||
|
|
||||||
if (address) {
|
if (address) {
|
||||||
switch (client_ip_family) {
|
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);
|
nm_setting_ip_config_add_address(s_ip6, address);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
_LOGW(LOGD_CORE, "Unknown address family: %s", client_ip);
|
nm_assert_not_reached();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
nm_ip_address_unref(address);
|
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);
|
_LOGW(LOGD_CORE, "Ignoring peer: %s (not implemented)\n", peer);
|
||||||
|
|
||||||
if (gateway_ip && *gateway_ip) {
|
if (gateway_ip && *gateway_ip) {
|
||||||
int addr_family = guess_ip_address_family(gateway_ip);
|
switch (get_ip_address_family(gateway_ip, FALSE)) {
|
||||||
|
case AF_INET:
|
||||||
if (nm_utils_ipaddr_is_valid(addr_family, gateway_ip)) {
|
g_object_set(s_ip4, NM_SETTING_IP_CONFIG_GATEWAY, gateway_ip, NULL);
|
||||||
switch (addr_family) {
|
break;
|
||||||
case AF_INET:
|
case AF_INET6:
|
||||||
g_object_set(s_ip4, NM_SETTING_IP_CONFIG_GATEWAY, gateway_ip, NULL);
|
g_object_set(s_ip6, NM_SETTING_IP_CONFIG_GATEWAY, gateway_ip, NULL);
|
||||||
break;
|
break;
|
||||||
case AF_INET6:
|
default:
|
||||||
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 {
|
|
||||||
_LOGW(LOGD_CORE, "Invalid gateway: %s", gateway_ip);
|
_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++) {
|
for (i = 0; i < nameservers->len; i++) {
|
||||||
ns = nameservers->pdata[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) {
|
if (addr_family == AF_UNSPEC) {
|
||||||
_LOGW(LOGD_CORE, "Unknown address family: %s", ns);
|
_LOGW(LOGD_CORE, "Unknown address family: %s", ns);
|
||||||
continue;
|
continue;
|
||||||
|
|
|
||||||
|
|
@ -165,9 +165,9 @@ ip_setting_add_from_block(GHashTable *nic, NMConnection *connection, GError **er
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
family = guess_ip_address_family(s_ipaddr);
|
family = get_ip_address_family(s_ipaddr, FALSE);
|
||||||
if (family == AF_UNSPEC)
|
if (family == AF_UNSPEC)
|
||||||
family = guess_ip_address_family(s_gateway);
|
family = get_ip_address_family(s_gateway, FALSE);
|
||||||
|
|
||||||
switch (family) {
|
switch (family) {
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
|
|
|
||||||
|
|
@ -1219,6 +1219,54 @@ test_team(void)
|
||||||
NM_CONNECTION_MULTI_CONNECT_SINGLE);
|
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
|
static void
|
||||||
test_ibft_ip_dev(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/ip", test_bond_ip);
|
||||||
g_test_add_func("/initrd/cmdline/bond/default", test_bond_default);
|
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/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", test_bridge);
|
||||||
g_test_add_func("/initrd/cmdline/bridge/default", test_bridge_default);
|
g_test_add_func("/initrd/cmdline/bridge/default", test_bridge_default);
|
||||||
g_test_add_func("/initrd/cmdline/bridge/ip", test_bridge_ip);
|
g_test_add_func("/initrd/cmdline/bridge/ip", test_bridge_ip);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue