summaryrefslogtreecommitdiff
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
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'.
-rw-r--r--include/nm-dbus-glib-types.h5
-rw-r--r--introspection/nm-ip4-config.xml40
-rw-r--r--introspection/nm-ip6-config.xml31
-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
-rw-r--r--libnm/nm-ip4-config.c46
-rw-r--r--libnm/nm-ip6-config.c46
-rw-r--r--src/nm-ip4-config.c133
-rw-r--r--src/nm-ip4-config.h8
-rw-r--r--src/nm-ip6-config.c130
-rw-r--r--src/nm-ip6-config.h8
15 files changed, 923 insertions, 86 deletions
diff --git a/include/nm-dbus-glib-types.h b/include/nm-dbus-glib-types.h
index 66f45685a7..1b41c9ff18 100644
--- a/include/nm-dbus-glib-types.h
+++ b/include/nm-dbus-glib-types.h
@@ -37,4 +37,9 @@
#define DBUS_TYPE_G_IP6_ROUTE (dbus_g_type_get_struct ("GValueArray", DBUS_TYPE_G_UCHAR_ARRAY, G_TYPE_UINT, DBUS_TYPE_G_UCHAR_ARRAY, G_TYPE_UINT, G_TYPE_INVALID))
#define DBUS_TYPE_G_ARRAY_OF_IP6_ROUTE (dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_IP6_ROUTE))
+#define DBUS_TYPE_NM_IP_ADDRESS (dbus_g_type_get_struct ("GValueArray", G_TYPE_STRING, G_TYPE_UINT, DBUS_TYPE_G_MAP_OF_STRING, G_TYPE_INVALID))
+#define DBUS_TYPE_NM_IP_ADDRESSES (dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_NM_IP_ADDRESS))
+#define DBUS_TYPE_NM_IP_ROUTE (dbus_g_type_get_struct ("GValueArray", G_TYPE_STRING, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_UINT, DBUS_TYPE_G_MAP_OF_STRING, G_TYPE_INVALID))
+#define DBUS_TYPE_NM_IP_ROUTES (dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_NM_IP_ROUTE))
+
#endif /* __NM_DBUS_GLIB_TYPES_H__ */
diff --git a/introspection/nm-ip4-config.xml b/introspection/nm-ip4-config.xml
index 6a8750b7f6..9807653495 100644
--- a/introspection/nm-ip4-config.xml
+++ b/introspection/nm-ip4-config.xml
@@ -2,20 +2,42 @@
<node name="/" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
<interface name="org.freedesktop.NetworkManager.IP4Config">
+ <property name="Addresses" type="aau" access="read">
+ <tp:docstring>
+ Array of arrays of IPv4 address/prefix/gateway. All 3
+ elements of each array are in network byte order. Essentially:
+ [(addr, prefix, gateway), (addr, prefix, gateway), ...]
+
+ Deprecated: use AddressData and Gateway
+ </tp:docstring>
+ </property>
+ <property name="AddressData" type="aa{sv}" access="read">
+ <tp:docstring>
+ Array of IP address data objects. All addresses will include
+ "address" (an IP address string), and "prefix" (a uint). Some
+ addresses may include additional attributes.
+ </tp:docstring>
+ </property>
<property name="Gateway" type="s" access="read">
<tp:docstring>The gateway in use.</tp:docstring>
</property>
- <property name="Addresses" type="aau" access="read">
- <tp:docstring>Array of tuples of IPv4 address/prefix/gateway. All 3
- elements of each tuple are in network byte order. Essentially:
- [(addr, prefix, gateway), (addr, prefix, gateway), ...]
+ <property name="Routes" type="aau" access="read">
+ <tp:docstring>
+ Arrays of IPv4 route/prefix/next-hop/metric. All 4 elements of
+ each tuple are in network byte order. 'route' and 'next hop'
+ are IPv4 addresses, while prefix and metric are simple
+ unsigned integers. Essentially: [(route, prefix, next-hop,
+ metric), (route, prefix, next-hop, metric), ...]
+
+ Deprecated: use RouteData
</tp:docstring>
</property>
- <property name="Routes" type="aau" access="read">
- <tp:docstring>Tuples of IPv4 route/prefix/next-hop/metric. All 4 elements
- of each tuple are in network byte order. 'route' and 'next hop' are IPv4
- addresses, while prefix and metric are simple unsigned integers. Essentially:
- [(route, prefix, next-hop, metric), (route, prefix, next-hop, metric), ...]
+ <property name="RouteData" type="aa{sv}" access="read">
+ <tp:docstring>
+ Array of IP route data objects. All routes will include "dest"
+ (an IP address string) and "prefix" (a uint). Some routes may
+ include "next-hop" (an IP address string), "metric" (a uint),
+ and additional attributes.
</tp:docstring>
</property>
<property name="Nameservers" type="au" access="read">
diff --git a/introspection/nm-ip6-config.xml b/introspection/nm-ip6-config.xml
index 55c519e701..985dd2e331 100644
--- a/introspection/nm-ip6-config.xml
+++ b/introspection/nm-ip6-config.xml
@@ -2,14 +2,37 @@
<node name="/" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
<interface name="org.freedesktop.NetworkManager.IP6Config">
+ <property name="Addresses" type="a(ayuay)" access="read">
+ <tp:docstring>
+ Array of tuples of IPv6 address/prefix/gateway.
+
+ Deprecated: use AddressData and Gateway.
+ </tp:docstring>
+ </property>
+ <property name="AddressData" type="aa{sv}" access="read">
+ <tp:docstring>
+ Array of IP address data objects. All addresses will include
+ "address" (an IP address string), and "prefix" (a uint). Some
+ addresses may include additional attributes.
+ </tp:docstring>
+ </property>
<property name="Gateway" type="s" access="read">
<tp:docstring>The gateway in use.</tp:docstring>
</property>
- <property name="Addresses" type="a(ayuay)" access="read">
- <tp:docstring>Tuples of IPv6 address/prefix/gateway.</tp:docstring>
- </property>
<property name="Routes" type="a(ayuayu)" access="read">
- <tp:docstring>Tuples of IPv6 route/prefix/next-hop/metric.</tp:docstring>
+ <tp:docstring>
+ Tuples of IPv6 route/prefix/next-hop/metric.
+
+ Deprecated: use RouteData
+ </tp:docstring>
+ </property>
+ <property name="RouteData" type="aa{sv}" access="read">
+ <tp:docstring>
+ Array of IP route data objects. All routes will include "dest"
+ (an IP address string) and "prefix" (a uint). Some routes may
+ include "next-hop" (an IP address string), "metric" (a uint),
+ and additional attributes.
+ </tp:docstring>
</property>
<property name="Nameservers" type="aay" access="read">
<tp:docstring>The nameservers in use.</tp:docstring>
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);
diff --git a/libnm/nm-ip4-config.c b/libnm/nm-ip4-config.c
index a37f835774..d242fe55db 100644
--- a/libnm/nm-ip4-config.c
+++ b/libnm/nm-ip4-config.c
@@ -40,6 +40,8 @@ typedef struct {
char **domains;
char **searches;
char **wins;
+
+ gboolean new_style_data;
} NMIP4ConfigPrivate;
enum {
@@ -69,10 +71,13 @@ nm_ip4_config_init (NMIP4Config *config)
}
static gboolean
-demarshal_ip4_address_array (NMObject *object, GParamSpec *pspec, GVariant *value, gpointer field)
+demarshal_ip4_addresses (NMObject *object, GParamSpec *pspec, GVariant *value, gpointer field)
{
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (object);
+ if (priv->new_style_data)
+ return TRUE;
+
g_ptr_array_unref (priv->addresses);
priv->addresses = nm_utils_ip4_addresses_from_variant (value, NULL);
_nm_object_queue_notify (object, NM_IP4_CONFIG_ADDRESSES);
@@ -81,6 +86,20 @@ demarshal_ip4_address_array (NMObject *object, GParamSpec *pspec, GVariant *valu
}
static gboolean
+demarshal_ip4_address_data (NMObject *object, GParamSpec *pspec, GVariant *value, gpointer field)
+{
+ NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (object);
+
+ priv->new_style_data = TRUE;
+
+ g_ptr_array_unref (priv->addresses);
+ priv->addresses = nm_utils_ip_addresses_from_variant (value, AF_INET);
+ _nm_object_queue_notify (object, NM_IP4_CONFIG_ADDRESSES);
+
+ return TRUE;
+}
+
+static gboolean
demarshal_ip4_array (NMObject *object, GParamSpec *pspec, GVariant *value, gpointer field)
{
char ***obj_field;
@@ -96,10 +115,13 @@ demarshal_ip4_array (NMObject *object, GParamSpec *pspec, GVariant *value, gpoin
}
static gboolean
-demarshal_ip4_routes_array (NMObject *object, GParamSpec *pspec, GVariant *value, gpointer field)
+demarshal_ip4_routes (NMObject *object, GParamSpec *pspec, GVariant *value, gpointer field)
{
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (object);
+ if (priv->new_style_data)
+ return TRUE;
+
g_ptr_array_unref (priv->routes);
priv->routes = nm_utils_ip4_routes_from_variant (value);
_nm_object_queue_notify (object, NM_IP4_CONFIG_ROUTES);
@@ -107,14 +129,30 @@ demarshal_ip4_routes_array (NMObject *object, GParamSpec *pspec, GVariant *value
return TRUE;
}
+static gboolean
+demarshal_ip4_route_data (NMObject *object, GParamSpec *pspec, GVariant *value, gpointer field)
+{
+ NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (object);
+
+ priv->new_style_data = TRUE;
+
+ g_ptr_array_unref (priv->routes);
+ priv->routes = nm_utils_ip_routes_from_variant (value, AF_INET);
+ _nm_object_queue_notify (object, NM_IP4_CONFIG_ROUTES);
+
+ return TRUE;
+}
+
static void
init_dbus (NMObject *object)
{
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (object);
const NMPropertiesInfo property_info[] = {
{ NM_IP4_CONFIG_GATEWAY, &priv->gateway, },
- { NM_IP4_CONFIG_ADDRESSES, &priv->addresses, demarshal_ip4_address_array },
- { NM_IP4_CONFIG_ROUTES, &priv->routes, demarshal_ip4_routes_array },
+ { NM_IP4_CONFIG_ADDRESSES, &priv->addresses, demarshal_ip4_addresses },
+ { "address-data", &priv->addresses, demarshal_ip4_address_data },
+ { NM_IP4_CONFIG_ROUTES, &priv->routes, demarshal_ip4_routes },
+ { "route-data", &priv->routes, demarshal_ip4_route_data },
{ NM_IP4_CONFIG_NAMESERVERS, &priv->nameservers, demarshal_ip4_array },
{ NM_IP4_CONFIG_DOMAINS, &priv->domains, },
{ NM_IP4_CONFIG_SEARCHES, &priv->searches, },
diff --git a/libnm/nm-ip6-config.c b/libnm/nm-ip6-config.c
index 82d377ee93..7318f5f6ea 100644
--- a/libnm/nm-ip6-config.c
+++ b/libnm/nm-ip6-config.c
@@ -39,6 +39,8 @@ typedef struct {
char **nameservers;
char **domains;
char **searches;
+
+ gboolean new_style_data;
} NMIP6ConfigPrivate;
enum {
@@ -54,10 +56,13 @@ enum {
};
static gboolean
-demarshal_ip6_address_array (NMObject *object, GParamSpec *pspec, GVariant *value, gpointer field)
+demarshal_ip6_addresses (NMObject *object, GParamSpec *pspec, GVariant *value, gpointer field)
{
NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (object);
+ if (priv->new_style_data)
+ return TRUE;
+
g_ptr_array_unref (priv->addresses);
priv->addresses = nm_utils_ip6_addresses_from_variant (value, NULL);
_nm_object_queue_notify (object, NM_IP6_CONFIG_ADDRESSES);
@@ -66,6 +71,20 @@ demarshal_ip6_address_array (NMObject *object, GParamSpec *pspec, GVariant *valu
}
static gboolean
+demarshal_ip6_address_data (NMObject *object, GParamSpec *pspec, GVariant *value, gpointer field)
+{
+ NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (object);
+
+ priv->new_style_data = TRUE;
+
+ g_ptr_array_unref (priv->addresses);
+ priv->addresses = nm_utils_ip_addresses_from_variant (value, AF_INET6);
+ _nm_object_queue_notify (object, NM_IP6_CONFIG_ADDRESSES);
+
+ return TRUE;
+}
+
+static gboolean
demarshal_ip6_nameserver_array (NMObject *object, GParamSpec *pspec, GVariant *value, gpointer field)
{
char ***obj_field;
@@ -81,10 +100,13 @@ demarshal_ip6_nameserver_array (NMObject *object, GParamSpec *pspec, GVariant *v
}
static gboolean
-demarshal_ip6_routes_array (NMObject *object, GParamSpec *pspec, GVariant *value, gpointer field)
+demarshal_ip6_routes (NMObject *object, GParamSpec *pspec, GVariant *value, gpointer field)
{
NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (object);
+ if (priv->new_style_data)
+ return TRUE;
+
g_ptr_array_unref (priv->routes);
priv->routes = nm_utils_ip6_routes_from_variant (value);
_nm_object_queue_notify (object, NM_IP6_CONFIG_ROUTES);
@@ -92,14 +114,30 @@ demarshal_ip6_routes_array (NMObject *object, GParamSpec *pspec, GVariant *value
return TRUE;
}
+static gboolean
+demarshal_ip6_route_data (NMObject *object, GParamSpec *pspec, GVariant *value, gpointer field)
+{
+ NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (object);
+
+ priv->new_style_data = TRUE;
+
+ g_ptr_array_unref (priv->routes);
+ priv->routes = nm_utils_ip_routes_from_variant (value, AF_INET6);
+ _nm_object_queue_notify (object, NM_IP6_CONFIG_ROUTES);
+
+ return TRUE;
+}
+
static void
init_dbus (NMObject *object)
{
NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (object);
const NMPropertiesInfo property_info[] = {
{ NM_IP6_CONFIG_GATEWAY, &priv->gateway, },
- { NM_IP6_CONFIG_ADDRESSES, &priv->addresses, demarshal_ip6_address_array },
- { NM_IP6_CONFIG_ROUTES, &priv->routes, demarshal_ip6_routes_array },
+ { NM_IP6_CONFIG_ADDRESSES, &priv->addresses, demarshal_ip6_addresses },
+ { "address-data", &priv->addresses, demarshal_ip6_address_data },
+ { NM_IP6_CONFIG_ROUTES, &priv->routes, demarshal_ip6_routes },
+ { "route-data", &priv->routes, demarshal_ip6_route_data },
{ NM_IP6_CONFIG_NAMESERVERS, &priv->nameservers, demarshal_ip6_nameserver_array },
{ NM_IP6_CONFIG_DOMAINS, &priv->domains, },
{ NM_IP6_CONFIG_SEARCHES, &priv->searches, },
diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c
index 12d3919e77..74a7556f38 100644
--- a/src/nm-ip4-config.c
+++ b/src/nm-ip4-config.c
@@ -59,9 +59,11 @@ G_STATIC_ASSERT (G_MAXUINT >= 0xFFFFFFFF);
enum {
PROP_0,
- PROP_GATEWAY,
+ PROP_ADDRESS_DATA,
PROP_ADDRESSES,
+ PROP_ROUTE_DATA,
PROP_ROUTES,
+ PROP_GATEWAY,
PROP_NAMESERVERS,
PROP_DOMAINS,
PROP_SEARCHES,
@@ -235,6 +237,8 @@ nm_ip4_config_capture (int ifindex, gboolean capture_resolv_conf)
}
/* actually, nobody should be connected to the signal, just to be sure, notify */
+ _NOTIFY (config, PROP_ADDRESS_DATA);
+ _NOTIFY (config, PROP_ROUTE_DATA);
_NOTIFY (config, PROP_ADDRESSES);
_NOTIFY (config, PROP_ROUTES);
if (priv->gateway != old_gateway)
@@ -1013,6 +1017,7 @@ nm_ip4_config_reset_addresses (NMIP4Config *config)
if (priv->addresses->len != 0) {
g_array_set_size (priv->addresses, 0);
+ _NOTIFY (config, PROP_ADDRESS_DATA);
_NOTIFY (config, PROP_ADDRESSES);
}
}
@@ -1070,6 +1075,7 @@ nm_ip4_config_add_address (NMIP4Config *config, const NMPlatformIP4Address *new)
g_array_append_val (priv->addresses, *new);
NOTIFY:
+ _NOTIFY (config, PROP_ADDRESS_DATA);
_NOTIFY (config, PROP_ADDRESSES);
}
@@ -1081,6 +1087,7 @@ nm_ip4_config_del_address (NMIP4Config *config, guint i)
g_return_if_fail (i < priv->addresses->len);
g_array_remove_index (priv->addresses, i);
+ _NOTIFY (config, PROP_ADDRESS_DATA);
_NOTIFY (config, PROP_ADDRESSES);
}
@@ -1125,6 +1132,7 @@ nm_ip4_config_reset_routes (NMIP4Config *config)
if (priv->routes->len != 0) {
g_array_set_size (priv->routes, 0);
+ _NOTIFY (config, PROP_ROUTE_DATA);
_NOTIFY (config, PROP_ROUTES);
}
}
@@ -1164,6 +1172,7 @@ nm_ip4_config_add_route (NMIP4Config *config, const NMPlatformIP4Route *new)
g_array_append_val (priv->routes, *new);
NOTIFY:
+ _NOTIFY (config, PROP_ROUTE_DATA);
_NOTIFY (config, PROP_ROUTES);
}
@@ -1175,6 +1184,7 @@ nm_ip4_config_del_route (NMIP4Config *config, guint i)
g_return_if_fail (i < priv->routes->len);
g_array_remove_index (priv->routes, i);
+ _NOTIFY (config, PROP_ROUTE_DATA);
_NOTIFY (config, PROP_ROUTES);
}
@@ -1705,11 +1715,41 @@ get_property (GObject *object, guint prop_id,
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (object);
switch (prop_id) {
- case PROP_GATEWAY:
- if (priv->gateway)
- g_value_set_string (value, nm_utils_inet4_ntop (priv->gateway, NULL));
- else
- g_value_set_string (value, NULL);
+ case PROP_ADDRESS_DATA:
+ {
+ GPtrArray *addresses = g_ptr_array_new ();
+ int naddr = nm_ip4_config_get_num_addresses (config);
+ int i;
+
+ for (i = 0; i < naddr; i++) {
+ const NMPlatformIP4Address *address = nm_ip4_config_get_address (config, i);
+ GValueArray *array = g_value_array_new (3);
+ GHashTable *attrs;
+ GValue val = { 0, };
+
+ g_value_init (&val, G_TYPE_STRING);
+ g_value_set_string (&val, nm_utils_inet4_ntop (address->address, NULL));
+ g_value_array_append (array, &val);
+ g_value_unset (&val);
+
+ g_value_init (&val, G_TYPE_UINT);
+ g_value_set_uint (&val, address->plen);
+ g_value_array_append (array, &val);
+ g_value_unset (&val);
+
+ g_value_init (&val, DBUS_TYPE_G_MAP_OF_STRING);
+ attrs = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
+ if (*address->label)
+ g_hash_table_insert (attrs, "label", g_strdup (address->label));
+ g_value_take_boxed (&val, attrs);
+ g_value_array_append (array, &val);
+ g_value_unset (&val);
+
+ g_ptr_array_add (addresses, array);
+ }
+
+ g_value_take_boxed (value, addresses);
+ }
break;
case PROP_ADDRESSES:
{
@@ -1732,6 +1772,53 @@ get_property (GObject *object, guint prop_id,
g_value_take_boxed (value, addresses);
}
break;
+ case PROP_ROUTE_DATA:
+ {
+ GPtrArray *routes = g_ptr_array_new ();
+ guint nroutes = nm_ip4_config_get_num_routes (config);
+ int i;
+
+ for (i = 0; i < nroutes; i++) {
+ const NMPlatformIP4Route *route = nm_ip4_config_get_route (config, i);
+ GValueArray *array = g_value_array_new (5);
+ GHashTable *attrs;
+ GValue val = { 0, };
+
+ g_value_init (&val, G_TYPE_STRING);
+ g_value_set_string (&val, nm_utils_inet4_ntop (route->network, NULL));
+ g_value_array_append (array, &val);
+ g_value_unset (&val);
+
+ g_value_init (&val, G_TYPE_UINT);
+ g_value_set_uint (&val, route->plen);
+ g_value_array_append (array, &val);
+ g_value_unset (&val);
+
+ g_value_init (&val, G_TYPE_STRING);
+ if (route->gateway)
+ g_value_set_string (&val, nm_utils_inet4_ntop (route->gateway, NULL));
+ else
+ g_value_set_string (&val, "");
+ g_value_array_append (array, &val);
+ g_value_unset (&val);
+
+ g_value_init (&val, G_TYPE_UINT);
+ g_value_set_uint (&val, route->metric);
+ g_value_array_append (array, &val);
+ g_value_unset (&val);
+
+ g_value_init (&val, DBUS_TYPE_G_MAP_OF_STRING);
+ attrs = g_hash_table_new (g_str_hash, g_str_equal);
+ g_value_take_boxed (&val, attrs);
+ g_value_array_append (array, &val);
+ g_value_unset (&val);
+
+ g_ptr_array_add (routes, array);
+ }
+
+ g_value_take_boxed (value, routes);
+ }
+ break;
case PROP_ROUTES:
{
GPtrArray *routes = g_ptr_array_new ();
@@ -1753,6 +1840,12 @@ get_property (GObject *object, guint prop_id,
g_value_take_boxed (value, routes);
}
break;
+ case PROP_GATEWAY:
+ if (priv->gateway)
+ g_value_set_string (value, nm_utils_inet4_ntop (priv->gateway, NULL));
+ else
+ g_value_set_string (value, NULL);
+ break;
case PROP_NAMESERVERS:
g_value_set_boxed (value, priv->nameservers);
break;
@@ -1781,19 +1874,29 @@ nm_ip4_config_class_init (NMIP4ConfigClass *config_class)
object_class->get_property = get_property;
object_class->finalize = finalize;
- obj_properties[PROP_GATEWAY] =
- g_param_spec_string (NM_IP4_CONFIG_GATEWAY, "", "",
- NULL,
- G_PARAM_READABLE |
- G_PARAM_STATIC_STRINGS);
+ obj_properties[PROP_ADDRESS_DATA] =
+ g_param_spec_boxed (NM_IP4_CONFIG_ADDRESS_DATA, "", "",
+ DBUS_TYPE_NM_IP_ADDRESSES,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_STRINGS);
obj_properties[PROP_ADDRESSES] =
- g_param_spec_boxed (NM_IP4_CONFIG_ADDRESSES, "", "",
- DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT,
+ g_param_spec_boxed (NM_IP4_CONFIG_ADDRESSES, "", "",
+ DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_STRINGS);
+ obj_properties[PROP_ROUTE_DATA] =
+ g_param_spec_boxed (NM_IP4_CONFIG_ROUTE_DATA, "", "",
+ DBUS_TYPE_NM_IP_ROUTES,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS);
obj_properties[PROP_ROUTES] =
- g_param_spec_boxed (NM_IP4_CONFIG_ROUTES, "", "",
- DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT,
+ g_param_spec_boxed (NM_IP4_CONFIG_ROUTES, "", "",
+ DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_STRINGS);
+ obj_properties[PROP_GATEWAY] =
+ g_param_spec_string (NM_IP4_CONFIG_GATEWAY, "", "",
+ NULL,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS);
obj_properties[PROP_NAMESERVERS] =
diff --git a/src/nm-ip4-config.h b/src/nm-ip4-config.h
index e9f2642af7..555f1678a7 100644
--- a/src/nm-ip4-config.h
+++ b/src/nm-ip4-config.h
@@ -41,14 +41,18 @@ typedef struct {
GObjectClass parent;
} NMIP4ConfigClass;
+#define NM_IP4_CONFIG_ADDRESS_DATA "address-data"
+#define NM_IP4_CONFIG_ROUTE_DATA "route-data"
#define NM_IP4_CONFIG_GATEWAY "gateway"
-#define NM_IP4_CONFIG_ADDRESSES "addresses"
-#define NM_IP4_CONFIG_ROUTES "routes"
#define NM_IP4_CONFIG_NAMESERVERS "nameservers"
#define NM_IP4_CONFIG_DOMAINS "domains"
#define NM_IP4_CONFIG_SEARCHES "searches"
#define NM_IP4_CONFIG_WINS_SERVERS "wins-servers"
+/* deprecated */
+#define NM_IP4_CONFIG_ADDRESSES "addresses"
+#define NM_IP4_CONFIG_ROUTES "routes"
+
GType nm_ip4_config_get_type (void);
diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c
index e007b20104..19552e0339 100644
--- a/src/nm-ip6-config.c
+++ b/src/nm-ip6-config.c
@@ -51,9 +51,11 @@ typedef struct {
enum {
PROP_0,
- PROP_GATEWAY,
+ PROP_ADDRESS_DATA,
PROP_ADDRESSES,
+ PROP_ROUTE_DATA,
PROP_ROUTES,
+ PROP_GATEWAY,
PROP_NAMESERVERS,
PROP_DOMAINS,
PROP_SEARCHES,
@@ -271,6 +273,7 @@ nm_ip6_config_addresses_sort (NMIP6Config *self, NMSettingIP6ConfigPrivacy use_t
g_free (data_pre);
if (changed) {
+ _NOTIFY (self, PROP_ADDRESS_DATA);
_NOTIFY (self, PROP_ADDRESSES);
return TRUE;
}
@@ -346,7 +349,9 @@ nm_ip6_config_capture (int ifindex, gboolean capture_resolv_conf, NMSettingIP6Co
/* actually, nobody should be connected to the signal, just to be sure, notify */
if (notify_nameservers)
_NOTIFY (config, PROP_NAMESERVERS);
+ _NOTIFY (config, PROP_ADDRESS_DATA);
_NOTIFY (config, PROP_ADDRESSES);
+ _NOTIFY (config, PROP_ROUTE_DATA);
_NOTIFY (config, PROP_ROUTES);
if (!IN6_ARE_ADDR_EQUAL (&priv->gateway, &old_gateway))
_NOTIFY (config, PROP_GATEWAY);
@@ -1016,6 +1021,7 @@ nm_ip6_config_reset_addresses (NMIP6Config *config)
if (priv->addresses->len != 0) {
g_array_set_size (priv->addresses, 0);
+ _NOTIFY (config, PROP_ADDRESS_DATA);
_NOTIFY (config, PROP_ADDRESSES);
}
}
@@ -1073,6 +1079,7 @@ nm_ip6_config_add_address (NMIP6Config *config, const NMPlatformIP6Address *new)
g_array_append_val (priv->addresses, *new);
NOTIFY:
+ _NOTIFY (config, PROP_ADDRESS_DATA);
_NOTIFY (config, PROP_ADDRESSES);
}
@@ -1084,6 +1091,7 @@ nm_ip6_config_del_address (NMIP6Config *config, guint i)
g_return_if_fail (i < priv->addresses->len);
g_array_remove_index (priv->addresses, i);
+ _NOTIFY (config, PROP_ADDRESS_DATA);
_NOTIFY (config, PROP_ADDRESSES);
}
@@ -1129,6 +1137,7 @@ nm_ip6_config_reset_routes (NMIP6Config *config)
if (priv->routes->len != 0) {
g_array_set_size (priv->routes, 0);
+ _NOTIFY (config, PROP_ROUTE_DATA);
_NOTIFY (config, PROP_ROUTES);
}
}
@@ -1168,6 +1177,7 @@ nm_ip6_config_add_route (NMIP6Config *config, const NMPlatformIP6Route *new)
g_array_append_val (priv->routes, *new);
NOTIFY:
+ _NOTIFY (config, PROP_ROUTE_DATA);
_NOTIFY (config, PROP_ROUTES);
}
@@ -1179,6 +1189,7 @@ nm_ip6_config_del_route (NMIP6Config *config, guint i)
g_return_if_fail (i < priv->routes->len);
g_array_remove_index (priv->routes, i);
+ _NOTIFY (config, PROP_ROUTE_DATA);
_NOTIFY (config, PROP_ROUTES);
}
@@ -1578,11 +1589,39 @@ get_property (GObject *object, guint prop_id,
NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (object);
switch (prop_id) {
- case PROP_GATEWAY:
- if (!IN6_IS_ADDR_UNSPECIFIED (&priv->gateway))
- g_value_set_string (value, nm_utils_inet6_ntop (&priv->gateway, NULL));
- else
- g_value_set_string (value, NULL);
+ case PROP_ADDRESS_DATA:
+ {
+ GPtrArray *addresses = g_ptr_array_new ();
+ int naddr = nm_ip6_config_get_num_addresses (config);
+ int i;
+
+ for (i = 0; i < naddr; i++) {
+ const NMPlatformIP6Address *address = nm_ip6_config_get_address (config, i);
+ GValueArray *array = g_value_array_new (3);
+ GHashTable *attrs;
+ GValue val = { 0, };
+
+ g_value_init (&val, G_TYPE_STRING);
+ g_value_set_string (&val, nm_utils_inet6_ntop (&address->address, NULL));
+ g_value_array_append (array, &val);
+ g_value_unset (&val);
+
+ g_value_init (&val, G_TYPE_UINT);
+ g_value_set_uint (&val, address->plen);
+ g_value_array_append (array, &val);
+ g_value_unset (&val);
+
+ g_value_init (&val, DBUS_TYPE_G_MAP_OF_STRING);
+ attrs = g_hash_table_new (g_str_hash, g_str_equal);
+ g_value_take_boxed (&val, attrs);
+ g_value_array_append (array, &val);
+ g_value_unset (&val);
+
+ g_ptr_array_add (addresses, array);
+ }
+
+ g_value_take_boxed (value, addresses);
+ }
break;
case PROP_ADDRESSES:
{
@@ -1626,6 +1665,53 @@ get_property (GObject *object, guint prop_id,
g_value_take_boxed (value, addresses);
}
break;
+ case PROP_ROUTE_DATA:
+ {
+ GPtrArray *routes = g_ptr_array_new ();
+ guint nroutes = nm_ip6_config_get_num_routes (config);
+ int i;
+
+ for (i = 0; i < nroutes; i++) {
+ const NMPlatformIP6Route *route = nm_ip6_config_get_route (config, i);
+ GValueArray *array = g_value_array_new (5);
+ GHashTable *attrs;
+ GValue val = { 0, };
+
+ g_value_init (&val, G_TYPE_STRING);
+ g_value_set_string (&val, nm_utils_inet6_ntop (&route->network, NULL));
+ g_value_array_append (array, &val);
+ g_value_unset (&val);
+
+ g_value_init (&val, G_TYPE_UINT);
+ g_value_set_uint (&val, route->plen);
+ g_value_array_append (array, &val);
+ g_value_unset (&val);
+
+ g_value_init (&val, G_TYPE_STRING);
+ if (memcmp (&route->gateway, &in6addr_any, sizeof (struct in6_addr)) != 0)
+ g_value_set_string (&val, nm_utils_inet6_ntop (&route->gateway, NULL));
+ else
+ g_value_set_string (&val, "");
+ g_value_array_append (array, &val);
+ g_value_unset (&val);
+
+ g_value_init (&val, G_TYPE_UINT);
+ g_value_set_uint (&val, route->metric);
+ g_value_array_append (array, &val);
+ g_value_unset (&val);
+
+ g_value_init (&val, DBUS_TYPE_G_MAP_OF_STRING);
+ attrs = g_hash_table_new (g_str_hash, g_str_equal);
+ g_value_take_boxed (&val, attrs);
+ g_value_array_append (array, &val);
+ g_value_unset (&val);
+
+ g_ptr_array_add (routes, array);
+ }
+
+ g_value_take_boxed (value, routes);
+ }
+ break;
case PROP_ROUTES:
{
GPtrArray *routes = g_ptr_array_new ();
@@ -1669,6 +1755,12 @@ get_property (GObject *object, guint prop_id,
g_value_take_boxed (value, routes);
}
break;
+ case PROP_GATEWAY:
+ if (!IN6_IS_ADDR_UNSPECIFIED (&priv->gateway))
+ g_value_set_string (value, nm_utils_inet6_ntop (&priv->gateway, NULL));
+ else
+ g_value_set_string (value, NULL);
+ break;
case PROP_NAMESERVERS:
nameservers_to_gvalue (priv->nameservers, value);
break;
@@ -1696,21 +1788,31 @@ nm_ip6_config_class_init (NMIP6ConfigClass *config_class)
object_class->finalize = finalize;
/* properties */
- obj_properties[PROP_GATEWAY] =
- g_param_spec_string (NM_IP6_CONFIG_GATEWAY, "", "",
- NULL,
- G_PARAM_READABLE |
- G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_ADDRESSES] =
- g_param_spec_boxed (NM_IP6_CONFIG_ADDRESSES, "", "",
- DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS,
+ obj_properties[PROP_ADDRESS_DATA] =
+ g_param_spec_boxed (NM_IP6_CONFIG_ADDRESS_DATA, "", "",
+ DBUS_TYPE_NM_IP_ADDRESSES,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS);
+ obj_properties[PROP_ADDRESSES] =
+ g_param_spec_boxed (NM_IP6_CONFIG_ADDRESSES, "", "",
+ DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_STRINGS);
+ obj_properties[PROP_ROUTE_DATA] =
+ g_param_spec_boxed (NM_IP6_CONFIG_ROUTE_DATA, "", "",
+ DBUS_TYPE_NM_IP_ROUTES,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_STRINGS);
obj_properties[PROP_ROUTES] =
g_param_spec_boxed (NM_IP6_CONFIG_ROUTES, "", "",
DBUS_TYPE_G_ARRAY_OF_IP6_ROUTE,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS);
+ obj_properties[PROP_GATEWAY] =
+ g_param_spec_string (NM_IP6_CONFIG_GATEWAY, "", "",
+ NULL,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_STRINGS);
obj_properties[PROP_NAMESERVERS] =
g_param_spec_boxed (NM_IP6_CONFIG_NAMESERVERS, "", "",
DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UCHAR,
diff --git a/src/nm-ip6-config.h b/src/nm-ip6-config.h
index 19eef01372..0174158832 100644
--- a/src/nm-ip6-config.h
+++ b/src/nm-ip6-config.h
@@ -42,13 +42,17 @@ typedef struct {
GObjectClass parent;
} NMIP6ConfigClass;
+#define NM_IP6_CONFIG_ADDRESS_DATA "address-data"
+#define NM_IP6_CONFIG_ROUTE_DATA "route-data"
#define NM_IP6_CONFIG_GATEWAY "gateway"
-#define NM_IP6_CONFIG_ADDRESSES "addresses"
-#define NM_IP6_CONFIG_ROUTES "routes"
#define NM_IP6_CONFIG_NAMESERVERS "nameservers"
#define NM_IP6_CONFIG_DOMAINS "domains"
#define NM_IP6_CONFIG_SEARCHES "searches"
+/* deprecated */
+#define NM_IP6_CONFIG_ADDRESSES "addresses"
+#define NM_IP6_CONFIG_ROUTES "routes"
+
GType nm_ip6_config_get_type (void);