summaryrefslogtreecommitdiff
path: root/libnm-core
diff options
context:
space:
mode:
authorDan Winship <danw@gnome.org>2014-10-21 08:33:18 -0400
committerDan Winship <danw@gnome.org>2014-11-07 07:49:40 -0500
commitd16905df633ceea08c93b6e982f660627d06ff34 (patch)
tree2578344aa6e4fcbfb0191c85880fbdc8d5845a0e /libnm-core
parentf17699f4e3dacb9358a8503c8b15efe3cb852b48 (diff)
downloadNetworkManager-d16905df633ceea08c93b6e982f660627d06ff34.tar.gz
libnm-core, libnm, core: add AddressData and RouteData properties
Add AddressData and RouteData properties to NMSettingIPConfig and NMIP[46]Config. These are like the existing "addresses" and "routes" properties, but using strings and containing additional attributes, like NMIPAddress and NMIPRoute. This only affects the D-Bus representations; there are no API changes to NMSettingIP{,4,6}Config or NMIP{4,6}Config as a result of this; the additional information is just added to the existing 'addresses' and 'routes' properties. NMSettingIP4Config and NMSettingIP6Config now always generate both old-style data ('addresses', 'address-labels', 'routes') and new-style data ('address-data', 'gateway', 'route-data') when serializing to D-Bus, for backward compatibility. When deserializing, they will fill in the 'addresses' and 'routes' properties from the new-style data if it is present (ignoring the old-style data), or from the old-style data if the new-style isn't present. The daemon-side NMIP4Config and NMIP6Config always emit changes for both 'Addresses'/'Routes' and 'AddressData'/'RouteData'. The libnm-side classes initially listen for changes on both properties, but start ignoring the 'Addresses' and 'Routes' properties once they know the daemon is also providing 'AddressData' and 'RouteData'.
Diffstat (limited to 'libnm-core')
-rw-r--r--libnm-core/nm-setting-ip-config.c3
-rw-r--r--libnm-core/nm-setting-ip4-config.c122
-rw-r--r--libnm-core/nm-setting-ip6-config.c121
-rw-r--r--libnm-core/nm-utils.c239
-rw-r--r--libnm-core/nm-utils.h7
-rw-r--r--libnm-core/tests/test-general.c70
6 files changed, 530 insertions, 32 deletions
diff --git a/libnm-core/nm-setting-ip-config.c b/libnm-core/nm-setting-ip-config.c
index 0ed612cd06..30e7b267c8 100644
--- a/libnm-core/nm-setting-ip-config.c
+++ b/libnm-core/nm-setting-ip-config.c
@@ -472,6 +472,7 @@ nm_ip_address_set_attribute (NMIPAddress *address, const char *name, GVariant *v
{
g_return_if_fail (address != NULL);
g_return_if_fail (name != NULL && *name != '\0');
+ g_return_if_fail (strcmp (name, "address") != 0 && strcmp (name, "prefix") != 0);
if (!address->attributes) {
address->attributes = g_hash_table_new_full (g_str_hash, g_str_equal,
@@ -1009,6 +1010,8 @@ nm_ip_route_set_attribute (NMIPRoute *route, const char *name, GVariant *value)
{
g_return_if_fail (route != NULL);
g_return_if_fail (name != NULL && *name != '\0');
+ g_return_if_fail ( strcmp (name, "dest") != 0 && strcmp (name, "prefix") != 0
+ && strcmp (name, "next-hop") != 0 && strcmp (name, "metric") != 0);
if (!route->attributes) {
route->attributes = g_hash_table_new_full (g_str_hash, g_str_equal,
diff --git a/libnm-core/nm-setting-ip4-config.c b/libnm-core/nm-setting-ip4-config.c
index 66f2ea997e..9eab49d7f5 100644
--- a/libnm-core/nm-setting-ip4-config.c
+++ b/libnm-core/nm-setting-ip4-config.c
@@ -269,9 +269,14 @@ ip4_addresses_set (NMSetting *setting,
char **labels, *gateway = NULL;
int i;
- addrs = nm_utils_ip4_addresses_from_variant (value, &gateway);
-
s_ip4 = g_variant_lookup_value (connection_dict, NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_VARIANT_TYPE_SETTING);
+ /* If 'address-data' is set then ignore 'addresses' */
+ if (g_variant_lookup (s_ip4, "address-data", "aa{sv}", NULL)) {
+ g_variant_unref (s_ip4);
+ return;
+ }
+
+ addrs = nm_utils_ip4_addresses_from_variant (value, &gateway);
if (g_variant_lookup (s_ip4, "address-labels", "^as", &labels)) {
for (i = 0; i < addrs->len && labels[i]; i++)
@@ -319,16 +324,95 @@ ip4_address_labels_get (NMSetting *setting,
}
static GVariant *
-ip4_routes_to_dbus (const GValue *prop_value)
+ip4_address_data_get (NMSetting *setting,
+ NMConnection *connection,
+ const char *property)
+{
+ GPtrArray *addrs;
+ GVariant *ret;
+
+ g_object_get (setting, NM_SETTING_IP_CONFIG_ADDRESSES, &addrs, NULL);
+ ret = nm_utils_ip_addresses_to_variant (addrs);
+ g_ptr_array_unref (addrs);
+
+ return ret;
+}
+
+static void
+ip4_address_data_set (NMSetting *setting,
+ GVariant *connection_dict,
+ const char *property,
+ GVariant *value)
+{
+ GPtrArray *addrs;
+
+ addrs = nm_utils_ip_addresses_from_variant (value, AF_INET);
+ g_object_set (setting, NM_SETTING_IP_CONFIG_ADDRESSES, addrs, NULL);
+ g_ptr_array_unref (addrs);
+}
+
+static GVariant *
+ip4_routes_get (NMSetting *setting,
+ const char *property)
+{
+ GPtrArray *routes;
+ GVariant *ret;
+
+ g_object_get (setting, property, &routes, NULL);
+ ret = nm_utils_ip4_routes_to_variant (routes);
+ g_ptr_array_unref (routes);
+
+ return ret;
+}
+
+static void
+ip4_routes_set (NMSetting *setting,
+ GVariant *connection_dict,
+ const char *property,
+ GVariant *value)
+{
+ GPtrArray *routes;
+ GVariant *s_ip4;
+
+ s_ip4 = g_variant_lookup_value (connection_dict, NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_VARIANT_TYPE_SETTING);
+ /* If 'route-data' is set then ignore 'routes' */
+ if (g_variant_lookup (s_ip4, "route-data", "aa{sv}", NULL)) {
+ g_variant_unref (s_ip4);
+ return;
+ }
+ g_variant_unref (s_ip4);
+
+ routes = nm_utils_ip4_routes_from_variant (value);
+ g_object_set (setting, property, routes, NULL);
+ g_ptr_array_unref (routes);
+}
+
+static GVariant *
+ip4_route_data_get (NMSetting *setting,
+ NMConnection *connection,
+ const char *property)
{
- return nm_utils_ip4_routes_to_variant (g_value_get_boxed (prop_value));
+ GPtrArray *routes;
+ GVariant *ret;
+
+ g_object_get (setting, NM_SETTING_IP_CONFIG_ROUTES, &routes, NULL);
+ ret = nm_utils_ip_routes_to_variant (routes);
+ g_ptr_array_unref (routes);
+
+ return ret;
}
static void
-ip4_routes_from_dbus (GVariant *dbus_value,
- GValue *prop_value)
+ip4_route_data_set (NMSetting *setting,
+ GVariant *connection_dict,
+ const char *property,
+ GVariant *value)
{
- g_value_take_boxed (prop_value, nm_utils_ip4_routes_from_variant (dbus_value));
+ GPtrArray *routes;
+
+ routes = nm_utils_ip_routes_from_variant (value, AF_INET);
+ g_object_set (setting, NM_SETTING_IP_CONFIG_ROUTES, routes, NULL);
+ g_ptr_array_unref (routes);
}
@@ -381,9 +465,23 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *ip4_class)
ip4_address_labels_get,
NULL);
- _nm_setting_class_transform_property (setting_class,
- NM_SETTING_IP_CONFIG_ROUTES,
- G_VARIANT_TYPE ("aau"),
- ip4_routes_to_dbus,
- ip4_routes_from_dbus);
+ _nm_setting_class_add_dbus_only_property (setting_class,
+ "address-data",
+ G_VARIANT_TYPE ("aa{sv}"),
+ ip4_address_data_get,
+ ip4_address_data_set);
+
+ _nm_setting_class_override_property (setting_class,
+ NM_SETTING_IP_CONFIG_ROUTES,
+ G_VARIANT_TYPE ("aau"),
+ ip4_routes_get,
+ ip4_routes_set,
+ NULL);
+
+ _nm_setting_class_add_dbus_only_property (setting_class,
+ "route-data",
+ G_VARIANT_TYPE ("aa{sv}"),
+ ip4_route_data_get,
+ ip4_route_data_set);
+
}
diff --git a/libnm-core/nm-setting-ip6-config.c b/libnm-core/nm-setting-ip6-config.c
index 9e3001157e..6e3ff6164e 100644
--- a/libnm-core/nm-setting-ip6-config.c
+++ b/libnm-core/nm-setting-ip6-config.c
@@ -214,9 +214,14 @@ ip6_addresses_set (NMSetting *setting,
GVariant *s_ip6;
char *gateway = NULL;
- addrs = nm_utils_ip6_addresses_from_variant (value, &gateway);
-
s_ip6 = g_variant_lookup_value (connection_dict, NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_VARIANT_TYPE_SETTING);
+ /* If 'address-data' is set then ignore 'addresses' */
+ if (g_variant_lookup (s_ip6, "address-data", "aa{sv}", NULL)) {
+ g_variant_unref (s_ip6);
+ return;
+ }
+
+ addrs = nm_utils_ip6_addresses_from_variant (value, &gateway);
if (gateway && !g_variant_lookup (s_ip6, "gateway", "s", NULL)) {
g_object_set (setting,
@@ -232,16 +237,95 @@ ip6_addresses_set (NMSetting *setting,
}
static GVariant *
-ip6_routes_to_dbus (const GValue *prop_value)
+ip6_address_data_get (NMSetting *setting,
+ NMConnection *connection,
+ const char *property)
+{
+ GPtrArray *addrs;
+ GVariant *ret;
+
+ g_object_get (setting, NM_SETTING_IP_CONFIG_ADDRESSES, &addrs, NULL);
+ ret = nm_utils_ip_addresses_to_variant (addrs);
+ g_ptr_array_unref (addrs);
+
+ return ret;
+}
+
+static void
+ip6_address_data_set (NMSetting *setting,
+ GVariant *connection_dict,
+ const char *property,
+ GVariant *value)
+{
+ GPtrArray *addrs;
+
+ addrs = nm_utils_ip_addresses_from_variant (value, AF_INET6);
+ g_object_set (setting, NM_SETTING_IP_CONFIG_ADDRESSES, addrs, NULL);
+ g_ptr_array_unref (addrs);
+}
+
+static GVariant *
+ip6_routes_get (NMSetting *setting,
+ const char *property)
+{
+ GPtrArray *routes;
+ GVariant *ret;
+
+ g_object_get (setting, property, &routes, NULL);
+ ret = nm_utils_ip6_routes_to_variant (routes);
+ g_ptr_array_unref (routes);
+
+ return ret;
+}
+
+static void
+ip6_routes_set (NMSetting *setting,
+ GVariant *connection_dict,
+ const char *property,
+ GVariant *value)
+{
+ GPtrArray *routes;
+ GVariant *s_ip6;
+
+ s_ip6 = g_variant_lookup_value (connection_dict, NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_VARIANT_TYPE_SETTING);
+ /* If 'route-data' is set then ignore 'routes' */
+ if (g_variant_lookup (s_ip6, "route-data", "aa{sv}", NULL)) {
+ g_variant_unref (s_ip6);
+ return;
+ }
+ g_variant_unref (s_ip6);
+
+ routes = nm_utils_ip6_routes_from_variant (value);
+ g_object_set (setting, property, routes, NULL);
+ g_ptr_array_unref (routes);
+}
+
+static GVariant *
+ip6_route_data_get (NMSetting *setting,
+ NMConnection *connection,
+ const char *property)
{
- return nm_utils_ip6_routes_to_variant (g_value_get_boxed (prop_value));
+ GPtrArray *routes;
+ GVariant *ret;
+
+ g_object_get (setting, NM_SETTING_IP_CONFIG_ROUTES, &routes, NULL);
+ ret = nm_utils_ip_routes_to_variant (routes);
+ g_ptr_array_unref (routes);
+
+ return ret;
}
static void
-ip6_routes_from_dbus (GVariant *dbus_value,
- GValue *prop_value)
+ip6_route_data_set (NMSetting *setting,
+ GVariant *connection_dict,
+ const char *property,
+ GVariant *value)
{
- g_value_take_boxed (prop_value, nm_utils_ip6_routes_from_variant (dbus_value));
+ GPtrArray *routes;
+
+ routes = nm_utils_ip_routes_from_variant (value, AF_INET6);
+ g_object_set (setting, NM_SETTING_IP_CONFIG_ROUTES, routes, NULL);
+ g_ptr_array_unref (routes);
}
static void
@@ -324,9 +408,22 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *ip6_class)
ip6_addresses_set,
NULL);
- _nm_setting_class_transform_property (setting_class,
- NM_SETTING_IP_CONFIG_ROUTES,
- G_VARIANT_TYPE ("a(ayuayu)"),
- ip6_routes_to_dbus,
- ip6_routes_from_dbus);
+ _nm_setting_class_add_dbus_only_property (setting_class,
+ "address-data",
+ G_VARIANT_TYPE ("aa{sv}"),
+ ip6_address_data_get,
+ ip6_address_data_set);
+
+ _nm_setting_class_override_property (setting_class,
+ NM_SETTING_IP_CONFIG_ROUTES,
+ G_VARIANT_TYPE ("a(ayuayu)"),
+ ip6_routes_get,
+ ip6_routes_set,
+ NULL);
+
+ _nm_setting_class_add_dbus_only_property (setting_class,
+ "route-data",
+ G_VARIANT_TYPE ("aa{sv}"),
+ ip6_route_data_get,
+ ip6_route_data_set);
}
diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c
index 62698eefc8..f8105da810 100644
--- a/libnm-core/nm-utils.c
+++ b/libnm-core/nm-utils.c
@@ -1712,6 +1712,245 @@ nm_utils_ip6_routes_from_variant (GVariant *value)
}
/**
+ * nm_utils_ip_addresses_to_variant:
+ * @addresses: (element-type NMIPAddress): an array of #NMIPAddress objects
+ *
+ * Utility function to convert a #GPtrArray of #NMIPAddress objects representing
+ * IPv4 or IPv6 addresses into a #GVariant of type 'aa{sv}' representing an
+ * array of new-style NetworkManager IP addresses. All addresses will include
+ * "address" (an IP address string), and "prefix" (a uint). Some addresses may
+ * include additional attributes.
+ *
+ * Returns: (transfer none): a new floating #GVariant representing @addresses.
+ **/
+GVariant *
+nm_utils_ip_addresses_to_variant (GPtrArray *addresses)
+{
+ GVariantBuilder builder;
+ int i;
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("aa{sv}"));
+
+ if (addresses) {
+ for (i = 0; i < addresses->len; i++) {
+ NMIPAddress *addr = addresses->pdata[i];
+ GVariantBuilder addr_builder;
+ char **names;
+ int n;
+
+ g_variant_builder_init (&addr_builder, G_VARIANT_TYPE ("a{sv}"));
+ g_variant_builder_add (&addr_builder, "{sv}",
+ "address",
+ g_variant_new_string (nm_ip_address_get_address (addr)));
+ g_variant_builder_add (&addr_builder, "{sv}",
+ "prefix",
+ g_variant_new_uint32 (nm_ip_address_get_prefix (addr)));
+
+ names = nm_ip_address_get_attribute_names (addr);
+ for (n = 0; names[n]; n++) {
+ g_variant_builder_add (&addr_builder, "{sv}",
+ names[n],
+ nm_ip_address_get_attribute (addr, names[n]));
+ }
+ g_strfreev (names);
+
+ g_variant_builder_add (&builder, "a{sv}", &addr_builder);
+ }
+ }
+
+ return g_variant_builder_end (&builder);
+}
+
+/**
+ * nm_utils_ip_addresses_from_variant:
+ * @value: a #GVariant of type 'aa{sv}'
+ * @family: an IP address family
+ *
+ * Utility function to convert a #GVariant representing a list of new-style
+ * NetworkManager IPv4 or IPv6 addresses (as described in the documentation for
+ * nm_utils_ip_addresses_to_variant()) into a #GPtrArray of #NMIPAddress
+ * objects.
+ *
+ * Returns: (transfer full) (element-type NMIPAddress): a newly allocated
+ * #GPtrArray of #NMIPAddress objects
+ **/
+GPtrArray *
+nm_utils_ip_addresses_from_variant (GVariant *value,
+ int family)
+{
+ GPtrArray *addresses;
+ GVariantIter iter, attrs_iter;
+ GVariant *addr_var;
+ const char *ip;
+ guint32 prefix;
+ const char *attr_name;
+ GVariant *attr_val;
+ NMIPAddress *addr;
+ GError *error = NULL;
+
+ g_return_val_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE ("aa{sv}")), NULL);
+
+ g_variant_iter_init (&iter, value);
+ addresses = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip_address_unref);
+
+ while (g_variant_iter_next (&iter, "@a{sv}", &addr_var)) {
+ if ( !g_variant_lookup (addr_var, "address", "&s", &ip)
+ || !g_variant_lookup (addr_var, "prefix", "u", &prefix)) {
+ g_warning ("Ignoring invalid address");
+ g_variant_unref (addr_var);
+ continue;
+ }
+
+ addr = nm_ip_address_new (family, ip, prefix, &error);
+ if (!addr) {
+ g_warning ("Ignoring invalid address: %s", error->message);
+ g_clear_error (&error);
+ g_variant_unref (addr_var);
+ continue;
+ }
+
+ g_variant_iter_init (&attrs_iter, addr_var);
+ while (g_variant_iter_next (&attrs_iter, "{&sv}", &attr_name, &attr_val)) {
+ if ( strcmp (attr_name, "address") != 0
+ && strcmp (attr_name, "prefix") != 0)
+ nm_ip_address_set_attribute (addr, attr_name, attr_val);
+ g_variant_unref (attr_val);
+ }
+
+ g_ptr_array_add (addresses, addr);
+ }
+
+ return addresses;
+}
+
+/**
+ * nm_utils_ip_routes_to_variant:
+ * @routes: (element-type NMIPRoute): an array of #NMIPRoute objects
+ *
+ * Utility function to convert a #GPtrArray of #NMIPRoute objects representing
+ * IPv4 or IPv6 routes into a #GVariant of type 'aa{sv}' representing an array
+ * of new-style NetworkManager IP routes (which are tuples of destination,
+ * prefix, next hop, metric, and additional attributes).
+ *
+ * Returns: (transfer none): a new floating #GVariant representing @routes.
+ **/
+GVariant *
+nm_utils_ip_routes_to_variant (GPtrArray *routes)
+{
+ GVariantBuilder builder;
+ int i;
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("aa{sv}"));
+
+ if (routes) {
+ for (i = 0; i < routes->len; i++) {
+ NMIPRoute *route = routes->pdata[i];
+ GVariantBuilder route_builder;
+ char **names;
+ int n;
+
+ g_variant_builder_init (&route_builder, G_VARIANT_TYPE ("a{sv}"));
+ g_variant_builder_add (&route_builder, "{sv}",
+ "dest",
+ g_variant_new_string (nm_ip_route_get_dest (route)));
+ g_variant_builder_add (&route_builder, "{sv}",
+ "prefix",
+ g_variant_new_uint32 (nm_ip_route_get_prefix (route)));
+ if (nm_ip_route_get_next_hop (route)) {
+ g_variant_builder_add (&route_builder, "{sv}",
+ "next-hop",
+ g_variant_new_string (nm_ip_route_get_next_hop (route)));
+ }
+ if (nm_ip_route_get_metric (route)) {
+ g_variant_builder_add (&route_builder, "{sv}",
+ "metric",
+ g_variant_new_uint32 (nm_ip_route_get_metric (route)));
+ }
+
+ names = nm_ip_route_get_attribute_names (route);
+ for (n = 0; names[n]; n++) {
+ g_variant_builder_add (&route_builder, "{sv}",
+ names[n],
+ nm_ip_route_get_attribute (route, names[n]));
+ }
+ g_strfreev (names);
+
+ g_variant_builder_add (&builder, "a{sv}", &route_builder);
+ }
+ }
+
+ return g_variant_builder_end (&builder);
+}
+
+/**
+ * nm_utils_ip_routes_from_variant:
+ * @value: a #GVariant of type 'aa{sv}'
+ * @family: an IP address family
+ *
+ * Utility function to convert a #GVariant representing a list of new-style
+ * NetworkManager IPv4 or IPv6 addresses (which are tuples of destination,
+ * prefix, next hop, metric, and additional attributes) into a #GPtrArray of
+ * #NMIPRoute objects.
+ *
+ * Returns: (transfer full) (element-type NMIPRoute): a newly allocated
+ * #GPtrArray of #NMIPRoute objects
+ **/
+GPtrArray *
+nm_utils_ip_routes_from_variant (GVariant *value,
+ int family)
+{
+ GPtrArray *routes;
+ GVariantIter iter, attrs_iter;
+ GVariant *route_var;
+ const char *dest, *next_hop;
+ guint32 prefix, metric;
+ const char *attr_name;
+ GVariant *attr_val;
+ NMIPRoute *route;
+ GError *error = NULL;
+
+ g_return_val_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE ("aa{sv}")), NULL);
+
+ g_variant_iter_init (&iter, value);
+ routes = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip_route_unref);
+
+ while (g_variant_iter_next (&iter, "@a{sv}", &route_var)) {
+ if ( !g_variant_lookup (route_var, "dest", "&s", &dest)
+ || !g_variant_lookup (route_var, "prefix", "u", &prefix)) {
+ g_warning ("Ignoring invalid address");
+ g_variant_unref (route_var);
+ continue;
+ }
+ if (!g_variant_lookup (route_var, "next-hop", "&s", &next_hop))
+ next_hop = NULL;
+ if (!g_variant_lookup (route_var, "metric", "u", &metric))
+ metric = 0;
+
+ route = nm_ip_route_new (family, dest, prefix, next_hop, metric, &error);
+ if (!route) {
+ g_warning ("Ignoring invalid route: %s", error->message);
+ g_clear_error (&error);
+ g_variant_unref (route_var);
+ continue;
+ }
+
+ g_variant_iter_init (&attrs_iter, route_var);
+ while (g_variant_iter_next (&attrs_iter, "{&sv}", &attr_name, &attr_val)) {
+ if ( strcmp (attr_name, "dest") != 0
+ && strcmp (attr_name, "prefix") != 0
+ && strcmp (attr_name, "next-hop") != 0
+ && strcmp (attr_name, "metric") != 0)
+ nm_ip_route_set_attribute (route, attr_name, attr_val);
+ g_variant_unref (attr_val);
+ }
+
+ g_ptr_array_add (routes, route);
+ }
+
+ return routes;
+}
+
+/**
* nm_utils_uuid_generate:
*
* Returns: a newly allocated UUID suitable for use as the #NMSettingConnection
diff --git a/libnm-core/nm-utils.h b/libnm-core/nm-utils.h
index 628fa0f5a6..25f09c45ea 100644
--- a/libnm-core/nm-utils.h
+++ b/libnm-core/nm-utils.h
@@ -117,6 +117,13 @@ GPtrArray *nm_utils_ip6_addresses_from_variant (GVariant *value,
GVariant *nm_utils_ip6_routes_to_variant (GPtrArray *routes);
GPtrArray *nm_utils_ip6_routes_from_variant (GVariant *value);
+GVariant *nm_utils_ip_addresses_to_variant (GPtrArray *addresses);
+GPtrArray *nm_utils_ip_addresses_from_variant (GVariant *value,
+ int family);
+GVariant *nm_utils_ip_routes_to_variant (GPtrArray *routes);
+GPtrArray *nm_utils_ip_routes_from_variant (GVariant *value,
+ int family);
+
char *nm_utils_uuid_generate (void);
char *nm_utils_uuid_generate_from_string (const char *s);
diff --git a/libnm-core/tests/test-general.c b/libnm-core/tests/test-general.c
index d66a9c9f6e..1bab4e011c 100644
--- a/libnm-core/tests/test-general.c
+++ b/libnm-core/tests/test-general.c
@@ -329,7 +329,7 @@ test_setting_ip4_config_labels (void)
GPtrArray *addrs;
char **labels;
NMConnection *conn;
- GVariant *dict, *setting_dict, *value;
+ GVariant *dict, *dict2, *setting_dict, *value;
GError *error = NULL;
s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new ();
@@ -395,7 +395,9 @@ test_setting_ip4_config_labels (void)
label = nm_ip_address_get_attribute (addr, "label");
g_assert (label == NULL);
- /* The labels should appear in the D-Bus serialization */
+ /* The labels should appear in the D-Bus serialization under both
+ * 'address-labels' and 'address-data'.
+ */
conn = nmtst_create_minimal_connection ("label test", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL);
nm_connection_add_setting (conn, NM_SETTING (s_ip4));
dict = nm_connection_to_dbus (conn, NM_CONNECTION_SERIALIZE_ALL);
@@ -403,19 +405,41 @@ test_setting_ip4_config_labels (void)
setting_dict = g_variant_lookup_value (dict, NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_VARIANT_TYPE_SETTING);
g_assert (setting_dict != NULL);
+
value = g_variant_lookup_value (setting_dict, "address-labels", G_VARIANT_TYPE_STRING_ARRAY);
g_assert (value != NULL);
-
g_variant_get (value, "^as", &labels);
g_assert_cmpint (g_strv_length (labels), ==, 2);
g_assert_cmpstr (labels[0], ==, "eth0:1");
g_assert_cmpstr (labels[1], ==, "");
-
- g_variant_unref (setting_dict);
g_variant_unref (value);
g_strfreev (labels);
- /* And should be deserialized */
+ value = g_variant_lookup_value (setting_dict, "address-data", G_VARIANT_TYPE ("aa{sv}"));
+ addrs = nm_utils_ip_addresses_from_variant (value, AF_INET);
+ g_variant_unref (value);
+ g_assert (addrs != NULL);
+ g_assert_cmpint (addrs->len, ==, 2);
+ addr = addrs->pdata[0];
+ label = nm_ip_address_get_attribute (addr, "label");
+ g_assert (label != NULL);
+ g_assert_cmpstr (g_variant_get_string (label, NULL), ==, "eth0:1");
+ addr = addrs->pdata[1];
+ label = nm_ip_address_get_attribute (addr, "label");
+ g_assert (label == NULL);
+ g_ptr_array_unref (addrs);
+
+ g_variant_unref (setting_dict);
+
+ /* We should be able to deserialize the labels from either 'address-labels'
+ * or 'address-data'.
+ */
+ dict2 = g_variant_ref (dict);
+
+ NMTST_VARIANT_EDITOR (dict,
+ NMTST_VARIANT_DROP_PROPERTY (NM_SETTING_IP4_CONFIG_SETTING_NAME,
+ "address-data");
+ );
conn = nm_simple_connection_new_from_dbus (dict, &error);
g_assert_no_error (error);
g_variant_unref (dict);
@@ -433,6 +457,28 @@ test_setting_ip4_config_labels (void)
label = nm_ip_address_get_attribute (addr, "label");
g_assert (label == NULL);
+ g_object_unref (conn);
+
+ NMTST_VARIANT_EDITOR (dict2,
+ NMTST_VARIANT_DROP_PROPERTY (NM_SETTING_IP4_CONFIG_SETTING_NAME,
+ "address-labels");
+ );
+ conn = nm_simple_connection_new_from_dbus (dict2, &error);
+ g_assert_no_error (error);
+ g_variant_unref (dict2);
+
+ s_ip4 = nm_connection_get_setting_ip4_config (conn);
+
+ addr = nm_setting_ip_config_get_address (s_ip4, 0);
+ g_assert_cmpstr (nm_ip_address_get_address (addr), ==, "2.2.2.2");
+ label = nm_ip_address_get_attribute (addr, "label");
+ g_assert_cmpstr (g_variant_get_string (label, NULL), ==, "eth0:1");
+
+ addr = nm_setting_ip_config_get_address (s_ip4, 1);
+ g_assert_cmpstr (nm_ip_address_get_address (addr), ==, "3.3.3.3");
+ label = nm_ip_address_get_attribute (addr, "label");
+ g_assert (label == NULL);
+
/* Test explicit property assignment */
g_object_get (G_OBJECT (s_ip4),
NM_SETTING_IP_CONFIG_ADDRESSES, &addrs,
@@ -3391,10 +3437,14 @@ test_setting_ip4_gateway (void)
g_variant_unref (ip4_dict);
- /* When deserializing, the first gateway in ipv4.addresses is copied to ipv4.gateway */
+ /* When deserializing an old-style connection, the gateway from the first address
+ * is copied to :gateway.
+ */
NMTST_VARIANT_EDITOR (conn_dict,
NMTST_VARIANT_DROP_PROPERTY (NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP_CONFIG_GATEWAY);
+ NMTST_VARIANT_DROP_PROPERTY (NM_SETTING_IP4_CONFIG_SETTING_NAME,
+ "address-data");
);
conn = nm_simple_connection_new_from_dbus (conn_dict, &error);
@@ -3460,10 +3510,14 @@ test_setting_ip6_gateway (void)
g_variant_unref (ip6_dict);
- /* When deserializing, the first gateway in ipv4.addresses is copied to ipv4.gateway */
+ /* When deserializing an old-style connection, the gateway from the first address
+ * is copied to :gateway.
+ */
NMTST_VARIANT_EDITOR (conn_dict,
NMTST_VARIANT_DROP_PROPERTY (NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP_CONFIG_GATEWAY);
+ NMTST_VARIANT_DROP_PROPERTY (NM_SETTING_IP6_CONFIG_SETTING_NAME,
+ "address-data");
);
conn = nm_simple_connection_new_from_dbus (conn_dict, &error);