libnm-util: convert from old IP6 address format to new
authorDan Williams <dcbw@redhat.com>
Mon, 19 Apr 2010 17:14:44 +0000 (10:14 -0700)
committerDan Williams <dcbw@redhat.com>
Mon, 19 Apr 2010 17:14:44 +0000 (10:14 -0700)
Ensure it still works correctly if something tries to set the
'addresses' property using the old GType.  Also make sure that
the various IP6 address comparison operations and string conversion
functions handle the gateway.

libnm-util/nm-param-spec-specialized.c
libnm-util/nm-utils.c
libnm-util/tests/test-general.c

index ad0febf..f5a362c 100644 (file)
@@ -19,7 +19,7 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * (C) Copyright 2007 - 2008 Red Hat, Inc.
+ * (C) Copyright 2007 - 2010 Red Hat, Inc.
  * (C) Copyright 2007 - 2008 Novell, Inc.
  */
 
@@ -377,6 +377,7 @@ nm_gvalue_ip6_address_compare (const GValue *value1, const GValue *value2)
        GValue *tmp_val;
        GByteArray *addr1, *addr2;
        guint32 prefix1, prefix2;
+       GByteArray *gw1, *gw2;
        gint ret = 0;
        int i;
 
@@ -387,8 +388,8 @@ nm_gvalue_ip6_address_compare (const GValue *value1, const GValue *value2)
        /* Since they are NM IPv6 address structures, we expect both
         * to contain two elements as specified in nm-dbus-glib-types.h.
         */
-       g_return_val_if_fail (values1->n_values == 2, 0);
-       g_return_val_if_fail (values2->n_values == 2, 0);
+       g_return_val_if_fail (values1->n_values == 3, 0);
+       g_return_val_if_fail (values2->n_values == 3, 0);
 
        /* First struct IPv6 address */
        tmp_val = g_value_array_get_nth (values1, 0);
@@ -396,6 +397,9 @@ nm_gvalue_ip6_address_compare (const GValue *value1, const GValue *value2)
        /* First struct IPv6 prefix */
        tmp_val = g_value_array_get_nth (values1, 1);
        prefix1 = g_value_get_uint (tmp_val);
+       /* First struct IPv6 gateway */
+       tmp_val = g_value_array_get_nth (values1, 2);
+       gw1 = g_value_get_boxed (tmp_val);
 
        /* Second struct IPv6 address */
        tmp_val = g_value_array_get_nth (values2, 0);
@@ -403,6 +407,9 @@ nm_gvalue_ip6_address_compare (const GValue *value1, const GValue *value2)
        /* Second struct IPv6 prefix */
        tmp_val = g_value_array_get_nth (values2, 1);
        prefix2 = g_value_get_uint (tmp_val);
+       /* Second struct IPv6 gateway */
+       tmp_val = g_value_array_get_nth (values2, 2);
+       gw2 = g_value_get_boxed (tmp_val);
 
        /* Compare IPv6 addresses */
        if (prefix1 != prefix2)
@@ -413,6 +420,11 @@ nm_gvalue_ip6_address_compare (const GValue *value1, const GValue *value2)
                        ret = addr1->data[i] < addr2->data[i] ? -1 : addr1->data[i] > addr2->data[i];
        }
 
+       if (!IN6_ARE_ADDR_EQUAL ((struct in6_addr *) gw1->data, (struct in6_addr *) gw2->data)) {
+               for (i = 0; ret == 0 && i < gw1->len; i++)
+                       ret = gw1->data[i] < gw2->data[i] ? -1 : gw1->data[i] > gw2->data[i];
+       }
+
        return ret;
 }
 
index 405288d..8081694 100644 (file)
@@ -275,6 +275,8 @@ nm_utils_init (GError **error)
                if (!crypto_init (error))
                        return FALSE;
 
+               _nm_utils_register_value_transformations ();
+
                atexit (nm_utils_deinit);
                initialized = TRUE;
        }
@@ -886,6 +888,19 @@ nm_utils_convert_ip6_addr_struct_array_to_string (const GValue *src_value, GValu
                        continue;
                }
                g_string_append_printf (printable, "px = %u", prefix);
+               g_string_append (printable, ", ");
+
+               /* IPv6 Gateway */
+               tmp = g_value_array_get_nth (elements, 2);
+               ba_addr = g_value_get_boxed (tmp);
+               if (ba_addr->len != 16) {
+                       g_string_append (printable, "invalid");
+                       continue;
+               }
+               addr = (struct in6_addr *) ba_addr->data;
+               memset (buf, 0, sizeof (buf));
+               nm_utils_inet6_ntop (addr, buf);
+               g_string_append_printf (printable, "gw = %s", buf);
                g_string_append (printable, " }");
        }
        g_string_append_c (printable, ']');
@@ -977,6 +992,58 @@ nm_utils_convert_ip6_route_struct_array_to_string (const GValue *src_value, GVal
        g_string_free (printable, FALSE);
 }
 
+#define OLD_DBUS_TYPE_G_IP6_ADDRESS (dbus_g_type_get_struct ("GValueArray", DBUS_TYPE_G_UCHAR_ARRAY, G_TYPE_UINT, G_TYPE_INVALID))
+#define OLD_DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS (dbus_g_type_get_collection ("GPtrArray", OLD_DBUS_TYPE_G_IP6_ADDRESS))
+
+static void
+nm_utils_convert_old_ip6_addr_array (const GValue *src_value, GValue *dst_value)
+{
+       GPtrArray *src_outer_array;
+       GPtrArray *dst_outer_array;
+       guint i;
+
+       g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), OLD_DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS));
+
+       src_outer_array = (GPtrArray *) g_value_get_boxed (src_value);
+       dst_outer_array = g_ptr_array_new ();
+
+       for (i = 0; src_outer_array && (i < src_outer_array->len); i++) {
+               GValueArray *src_addr_array;
+               GValueArray *dst_addr_array;
+               GValue element = {0, };
+               GValue *src_addr, *src_prefix;
+               GByteArray *ba;
+
+               src_addr_array = (GValueArray *) g_ptr_array_index (src_outer_array, i);
+
+               if (   (src_addr_array->n_values != 2)
+                   || (G_VALUE_TYPE (g_value_array_get_nth (src_addr_array, 0)) != DBUS_TYPE_G_UCHAR_ARRAY)
+                   || (G_VALUE_TYPE (g_value_array_get_nth (src_addr_array, 1)) != G_TYPE_UINT)) {
+                       g_warning ("%s: invalid old IPv6 address type", __func__);
+                       return;
+               }
+
+               dst_addr_array = g_value_array_new (3);
+
+               src_addr = g_value_array_get_nth (src_addr_array, 0);
+               g_value_array_append (dst_addr_array, src_addr);
+               src_prefix = g_value_array_get_nth (src_addr_array, 1);
+               g_value_array_append (dst_addr_array, src_prefix);
+
+               /* Blank Gateway */
+               g_value_init (&element, DBUS_TYPE_G_UCHAR_ARRAY);
+               ba = g_byte_array_new ();
+               g_byte_array_append (ba, (guint8 *) "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16);
+               g_value_take_boxed (&element, ba);
+               g_value_array_append (dst_addr_array, &element);
+               g_value_unset (&element);
+
+               g_ptr_array_add (dst_outer_array, dst_addr_array);
+       }
+
+       g_value_take_boxed (dst_value, dst_outer_array);
+}
+
 void
 _nm_utils_register_value_transformations (void)
 {
@@ -1013,6 +1080,9 @@ _nm_utils_register_value_transformations (void)
                g_value_register_transform_func (DBUS_TYPE_G_ARRAY_OF_IP6_ROUTE,
                                                 G_TYPE_STRING, 
                                                 nm_utils_convert_ip6_route_struct_array_to_string);
+               g_value_register_transform_func (OLD_DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS,
+                                                DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS,
+                                                nm_utils_convert_old_ip6_addr_array);
                registered = TRUE;
        }
 }
index d00ec99..9530445 100644 (file)
@@ -15,7 +15,7 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
- * Copyright (C) 2008 - 2009 Red Hat, Inc.
+ * Copyright (C) 2008 - 2010 Red Hat, Inc.
  *
  */
 
@@ -28,7 +28,8 @@
 
 #include "nm-setting-connection.h"
 #include "nm-setting-vpn.h"
-
+#include "nm-setting-ip6-config.h"
+#include "nm-dbus-glib-types.h"
 
 static void
 vpn_check_func (const char *key, const char *value, gpointer user_data)
@@ -128,6 +129,99 @@ test_setting_vpn_items (void)
        g_object_unref (s_vpn);
 }
 
+#define OLD_DBUS_TYPE_G_IP6_ADDRESS (dbus_g_type_get_struct ("GValueArray", DBUS_TYPE_G_UCHAR_ARRAY, G_TYPE_UINT, G_TYPE_INVALID))
+#define OLD_DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS (dbus_g_type_get_collection ("GPtrArray", OLD_DBUS_TYPE_G_IP6_ADDRESS))
+
+/* Test that setting the IPv6 setting's 'addresses' property using the old
+ * IPv6 address format still works, i.e. that the GValue transformation function
+ * from old->new is working correctly.
+ */
+static void
+test_setting_ip6_config_old_address_array (void)
+{
+       NMSettingIP6Config *s_ip6;
+       GPtrArray *addresses, *read_addresses;
+       GValueArray *array, *read_array;
+       GValue element = {0, }, written_value = {0, }, read_value = {0, };
+       GByteArray *ba;
+       const guint8 addr[16] = { 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11,
+                                 0x11, 0x22, 0x33, 0x44, 0x66, 0x77, 0x88, 0x99 };
+       const guint8 gw[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+       guint32 prefix = 56;
+       GValue *read_addr, *read_prefix, *read_gw;
+
+       s_ip6 = (NMSettingIP6Config *) nm_setting_ip6_config_new ();
+       ASSERT (s_ip6 != NULL,
+               "ip6-old-addr", "error creating IP6 setting");
+
+       g_value_init (&written_value, OLD_DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS);
+
+       addresses = g_ptr_array_new ();
+       array = g_value_array_new (3);
+
+       /* IP address */
+       g_value_init (&element, DBUS_TYPE_G_UCHAR_ARRAY);
+       ba = g_byte_array_new ();
+       g_byte_array_append (ba, &addr[0], sizeof (addr));
+       g_value_take_boxed (&element, ba);
+       g_value_array_append (array, &element);
+       g_value_unset (&element);
+
+       /* Prefix */
+       g_value_init (&element, G_TYPE_UINT);
+       g_value_set_uint (&element, prefix);
+       g_value_array_append (array, &element);
+       g_value_unset (&element);
+
+       g_ptr_array_add (addresses, array);
+       g_value_set_boxed (&written_value, addresses);
+
+       /* Set the address array on the object */
+       g_object_set_property (G_OBJECT (s_ip6), NM_SETTING_IP6_CONFIG_ADDRESSES, &written_value);
+
+       /* Get it back so we can compare it */
+       g_value_init (&read_value, DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS);
+       g_object_get_property (G_OBJECT (s_ip6), NM_SETTING_IP6_CONFIG_ADDRESSES, &read_value);
+
+       ASSERT (G_VALUE_HOLDS (&read_value, DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS),
+               "ip6-old-addr", "wrong addresses property value type '%s'",
+               G_VALUE_TYPE_NAME (&read_value));
+
+       read_addresses = (GPtrArray *) g_value_get_boxed (&read_value);
+       ASSERT (read_addresses != NULL,
+               "ip6-old-addr", "missing addresses on readback");
+       ASSERT (read_addresses->len == 1,
+               "ip6-old-addr", "expected one address on readback");
+
+       read_array = (GValueArray *) g_ptr_array_index (read_addresses, 0);
+
+       read_addr = g_value_array_get_nth (read_array, 0);
+       ba = g_value_get_boxed (read_addr);
+       ASSERT (ba->len == sizeof (addr),
+               "ip6-old-addr", "unexpected address item length %d", ba->len);
+       ASSERT (memcmp (ba->data, &addr[0], sizeof (addr)) == 0,
+               "ip6-old-addr", "unexpected failure comparing addresses");
+
+       read_prefix = g_value_array_get_nth (read_array, 1);
+       ASSERT (g_value_get_uint (read_prefix) == prefix,
+               "ip6-old-addr", "unexpected failure comparing prefix");
+
+       /* Ensure the gateway is all zeros, which is how the 2-item to 3-item
+        * conversion happens.
+        */
+       read_gw = g_value_array_get_nth (read_array, 2);
+       ba = g_value_get_boxed (read_gw);
+       ASSERT (ba->len == sizeof (gw),
+               "ip6-old-addr", "unexpected gateway item length %d", ba->len);
+       ASSERT (memcmp (ba->data, &gw[0], sizeof (gw)) == 0,
+               "ip6-old-addr", "unexpected failure comparing gateways");
+
+       g_value_unset (&written_value);
+       g_value_unset (&read_value);
+       g_object_unref (s_ip6);
+}
+
 int main (int argc, char **argv)
 {
        GError *error = NULL;
@@ -142,6 +236,7 @@ int main (int argc, char **argv)
 
        /* The tests */
        test_setting_vpn_items ();
+       test_setting_ip6_config_old_address_array ();
 
        base = g_path_get_basename (argv[0]);
        fprintf (stdout, "%s: SUCCESS\n", base);