libnm-core: fix the rule for parsing 'gateway' out of 'addresses' (rh #1170199)

We were always using the gateway field of the first address in
ipv4.addresses / ipv6.addresses to set the gateway, but to be
compatible with old behavior, we should actually be using the first
non-0 gateway field (if the first one is 0).
This commit is contained in:
Dan Winship
2014-12-03 11:10:17 -05:00
parent 3cf2fbbf47
commit cb025dba5b
2 changed files with 84 additions and 26 deletions

View File

@@ -1228,14 +1228,12 @@ nm_utils_ip4_addresses_from_variant (GVariant *value, char **out_gateway)
}
addr = nm_ip_address_new_binary (AF_INET, &addr_array[0], addr_array[1], &error);
if (addresses->len == 0 && out_gateway) {
if (addr_array[2])
*out_gateway = g_strdup (nm_utils_inet4_ntop (addr_array[2], NULL));
}
if (addr)
if (addr) {
g_ptr_array_add (addresses, addr);
else {
if (addr_array[2] && out_gateway && !*out_gateway)
*out_gateway = g_strdup (nm_utils_inet4_ntop (addr_array[2], NULL));
} else {
g_warning ("Ignoring invalid IP4 address: %s", error->message);
g_clear_error (&error);
}
@@ -1586,21 +1584,21 @@ nm_utils_ip6_addresses_from_variant (GVariant *value, char **out_gateway)
goto next;
}
if (addresses->len == 0 && out_gateway) {
gateway_bytes = g_variant_get_fixed_array (gateway_var, &gateway_len, 1);
if (gateway_len != 16) {
g_warning ("%s: ignoring invalid IP6 address of length %d",
__func__, (int) gateway_len);
goto next;
}
if (!IN6_IS_ADDR_UNSPECIFIED (gateway_bytes))
*out_gateway = g_strdup (nm_utils_inet6_ntop (gateway_bytes, NULL));
}
addr = nm_ip_address_new_binary (AF_INET6, addr_bytes, prefix, &error);
if (addr)
if (addr) {
g_ptr_array_add (addresses, addr);
else {
if (out_gateway && !*out_gateway) {
gateway_bytes = g_variant_get_fixed_array (gateway_var, &gateway_len, 1);
if (gateway_len != 16) {
g_warning ("%s: ignoring invalid IP6 address of length %d",
__func__, (int) gateway_len);
goto next;
}
if (!IN6_IS_ADDR_UNSPECIFIED (gateway_bytes))
*out_gateway = g_strdup (nm_utils_inet6_ntop (gateway_bytes, NULL));
}
} else {
g_warning ("Ignoring invalid IP4 address: %s", error->message);
g_clear_error (&error);
}

View File

@@ -3561,6 +3561,9 @@ test_setting_ip4_gateway (void)
GVariant *conn_dict, *ip4_dict, *value;
GVariantIter iter;
GVariant *addr_var;
guint32 addr_vals_0[] = { 0x0a01a8c0, 0x00000018, 0x00000000 };
guint32 addr_vals_1[] = { 0x0b01a8c0, 0x00000018, 0x0101a8c0 };
GVariantBuilder addrs_builder;
GError *error = NULL;
/* When serializing on the daemon side, ipv4.gateway is copied to the first
@@ -3610,8 +3613,8 @@ test_setting_ip4_gateway (void)
g_variant_unref (ip4_dict);
/* When deserializing an old-style connection, the gateway from the first address
* is copied to :gateway.
/* When deserializing an old-style connection, the first non-0 gateway in
* ipv4.addresses is copied to :gateway.
*/
NMTST_VARIANT_EDITOR (conn_dict,
NMTST_VARIANT_DROP_PROPERTY (NM_SETTING_IP4_CONFIG_SETTING_NAME,
@@ -3621,13 +3624,35 @@ test_setting_ip4_gateway (void)
);
conn = nm_simple_connection_new_from_dbus (conn_dict, &error);
g_variant_unref (conn_dict);
g_assert_no_error (error);
s_ip4 = (NMSettingIPConfig *) nm_connection_get_setting_ip4_config (conn);
g_assert_cmpstr (nm_setting_ip_config_get_gateway (s_ip4), ==, "192.168.1.1");
g_object_unref (conn);
/* Try again with the gateway in the second address. */
g_variant_builder_init (&addrs_builder, G_VARIANT_TYPE ("aau"));
g_variant_builder_add (&addrs_builder, "@au",
g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32,
addr_vals_0, 3, 4));
g_variant_builder_add (&addrs_builder, "@au",
g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32,
addr_vals_1, 3, 4));
NMTST_VARIANT_EDITOR (conn_dict,
NMTST_VARIANT_CHANGE_PROPERTY (NM_SETTING_IP4_CONFIG_SETTING_NAME,
"addresses", "aau", &addrs_builder);
);
conn = nm_simple_connection_new_from_dbus (conn_dict, &error);
g_assert_no_error (error);
g_variant_unref (conn_dict);
s_ip4 = (NMSettingIPConfig *) nm_connection_get_setting_ip4_config (conn);
g_assert_cmpstr (nm_setting_ip_config_get_gateway (s_ip4), ==, "192.168.1.1");
g_object_unref (conn);
}
static void
@@ -3639,6 +3664,13 @@ test_setting_ip6_gateway (void)
GVariant *conn_dict, *ip6_dict, *value;
GVariantIter iter;
GVariant *gateway_var;
GVariantBuilder addrs_builder;
guint8 addr_bytes_0[] = { 0xab, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a };
guint8 addr_bytes_1[] = { 0xab, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b };
guint8 gateway_bytes_1[] = { 0xab, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 };
GError *error = NULL;
/* When serializing on the daemon side, ipv6.gateway is copied to the first
@@ -3687,8 +3719,8 @@ test_setting_ip6_gateway (void)
g_variant_unref (ip6_dict);
/* When deserializing an old-style connection, the gateway from the first address
* is copied to :gateway.
/* When deserializing an old-style connection, the first non-0 gateway in
* ipv6.addresses is copied to :gateway.
*/
NMTST_VARIANT_EDITOR (conn_dict,
NMTST_VARIANT_DROP_PROPERTY (NM_SETTING_IP6_CONFIG_SETTING_NAME,
@@ -3698,13 +3730,41 @@ test_setting_ip6_gateway (void)
);
conn = nm_simple_connection_new_from_dbus (conn_dict, &error);
g_variant_unref (conn_dict);
g_assert_no_error (error);
s_ip6 = (NMSettingIPConfig *) nm_connection_get_setting_ip6_config (conn);
g_assert_cmpstr (nm_setting_ip_config_get_gateway (s_ip6), ==, "abcd::1");
g_object_unref (conn);
/* Try again with the gateway in the second address. */
g_variant_builder_init (&addrs_builder, G_VARIANT_TYPE ("a(ayuay)"));
g_variant_builder_add (&addrs_builder, "(@ayu@ay)",
g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
addr_bytes_0, 16, 1),
64,
g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
&in6addr_any, 16, 1));
g_variant_builder_add (&addrs_builder, "(@ayu@ay)",
g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
addr_bytes_1, 16, 1),
64,
g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
gateway_bytes_1, 16, 1));
NMTST_VARIANT_EDITOR (conn_dict,
NMTST_VARIANT_CHANGE_PROPERTY (NM_SETTING_IP6_CONFIG_SETTING_NAME,
"addresses", "a(ayuay)", &addrs_builder);
);
conn = nm_simple_connection_new_from_dbus (conn_dict, &error);
g_assert_no_error (error);
g_variant_unref (conn_dict);
s_ip6 = (NMSettingIPConfig *) nm_connection_get_setting_ip6_config (conn);
g_assert_cmpstr (nm_setting_ip_config_get_gateway (s_ip6), ==, "abcd::1");
g_object_unref (conn);
}
typedef struct {