diff options
author | Dan Winship <danw@redhat.com> | 2014-12-03 11:10:17 -0500 |
---|---|---|
committer | Dan Winship <danw@redhat.com> | 2014-12-03 16:31:50 -0500 |
commit | cb025dba5b39ba40474d9dbb23fa651dc9aa8e01 (patch) | |
tree | 01a2e6438ff01c04c384d80d8ca0d22993434746 | |
parent | 3cf2fbbf47dbb6a2f7a077b84d7bb50374f83f27 (diff) | |
download | NetworkManager-cb025dba5b39ba40474d9dbb23fa651dc9aa8e01.tar.gz |
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).
-rw-r--r-- | libnm-core/nm-utils.c | 38 | ||||
-rw-r--r-- | libnm-core/tests/test-general.c | 72 |
2 files changed, 84 insertions, 26 deletions
diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c index 9ccb107c61..f1f5a9e8ca 100644 --- a/libnm-core/nm-utils.c +++ b/libnm-core/nm-utils.c @@ -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); } diff --git a/libnm-core/tests/test-general.c b/libnm-core/tests/test-general.c index 1a0ee99d52..76d6d0ff80 100644 --- a/libnm-core/tests/test-general.c +++ b/libnm-core/tests/test-general.c @@ -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 { |