diff options
-rw-r--r-- | include/nm-dbus-glib-types.h | 5 | ||||
-rw-r--r-- | introspection/nm-ip4-config.xml | 40 | ||||
-rw-r--r-- | introspection/nm-ip6-config.xml | 31 | ||||
-rw-r--r-- | libnm-core/nm-setting-ip-config.c | 3 | ||||
-rw-r--r-- | libnm-core/nm-setting-ip4-config.c | 122 | ||||
-rw-r--r-- | libnm-core/nm-setting-ip6-config.c | 121 | ||||
-rw-r--r-- | libnm-core/nm-utils.c | 239 | ||||
-rw-r--r-- | libnm-core/nm-utils.h | 7 | ||||
-rw-r--r-- | libnm-core/tests/test-general.c | 70 | ||||
-rw-r--r-- | libnm/nm-ip4-config.c | 46 | ||||
-rw-r--r-- | libnm/nm-ip6-config.c | 46 | ||||
-rw-r--r-- | src/nm-ip4-config.c | 133 | ||||
-rw-r--r-- | src/nm-ip4-config.h | 8 | ||||
-rw-r--r-- | src/nm-ip6-config.c | 130 | ||||
-rw-r--r-- | src/nm-ip6-config.h | 8 |
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); |