diff options
Diffstat (limited to 'src/nm-ip6-config.c')
| -rw-r--r-- | src/nm-ip6-config.c | 557 |
1 files changed, 345 insertions, 212 deletions
diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c index f68c4339..fd63dcb4 100644 --- a/src/nm-ip6-config.c +++ b/src/nm-ip6-config.c @@ -24,26 +24,23 @@ #include <string.h> #include <arpa/inet.h> +#include "nm-default.h" #include "nm-ip6-config.h" -#include "nm-glib-compat.h" #include "nm-utils.h" #include "nm-platform.h" -#include "nm-dbus-manager.h" -#include "nm-dbus-glib-types.h" -#include "nm-ip6-config-glue.h" #include "nm-route-manager.h" +#include "nm-core-internal.h" #include "NetworkManagerUtils.h" #include "nm-macros-internal.h" -#include "nm-core-internal.h" -G_DEFINE_TYPE (NMIP6Config, nm_ip6_config, G_TYPE_OBJECT) +#include "nmdbus-ip6-config.h" -#define NM_IP6_CONFIG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_IP6_CONFIG, NMIP6ConfigPrivate)) +G_DEFINE_TYPE (NMIP6Config, nm_ip6_config, NM_TYPE_EXPORTED_OBJECT) -typedef struct { - char *path; +#define NM_IP6_CONFIG_GET_PRIVATE(o) ((o)->priv) +typedef struct _NMIP6ConfigPrivate { gboolean never_default; struct in6_addr gateway; GArray *addresses; @@ -51,13 +48,16 @@ typedef struct { GArray *nameservers; GPtrArray *domains; GPtrArray *searches; + GPtrArray *dns_options; guint32 mss; + int ifindex; gint64 route_metric; } NMIP6ConfigPrivate; enum { PROP_0, + PROP_IFINDEX, PROP_ADDRESS_DATA, PROP_ADDRESSES, PROP_ROUTE_DATA, @@ -66,6 +66,7 @@ enum { PROP_NAMESERVERS, PROP_DOMAINS, PROP_SEARCHES, + PROP_DNS_OPTIONS, LAST_PROP }; @@ -74,29 +75,18 @@ static GParamSpec *obj_properties[LAST_PROP] = { NULL, }; NMIP6Config * -nm_ip6_config_new (void) -{ - return (NMIP6Config *) g_object_new (NM_TYPE_IP6_CONFIG, NULL); -} - -void -nm_ip6_config_export (NMIP6Config *config) +nm_ip6_config_new (int ifindex) { - NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); - static guint32 counter = 0; - - if (!priv->path) { - priv->path = g_strdup_printf (NM_DBUS_PATH "/IP6Config/%d", counter++); - nm_dbus_manager_register_object (nm_dbus_manager_get (), priv->path, config); - } + g_return_val_if_fail (ifindex >= -1, NULL); + return (NMIP6Config *) g_object_new (NM_TYPE_IP6_CONFIG, + NM_IP6_CONFIG_IFINDEX, ifindex, + NULL); } -const char * -nm_ip6_config_get_dbus_path (const NMIP6Config *config) +int +nm_ip6_config_get_ifindex (const NMIP6Config *config) { - NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); - - return priv->path; + return NM_IP6_CONFIG_GET_PRIVATE (config)->ifindex; } /******************************************************************/ @@ -130,9 +120,10 @@ same_prefix (const struct in6_addr *address1, const struct in6_addr *address2, i */ gboolean nm_ip6_config_capture_resolv_conf (GArray *nameservers, + GPtrArray *dns_options, const char *rc_contents) { - GPtrArray *read_ns; + GPtrArray *read_ns, *read_options; guint i, j; gboolean changed = FALSE; @@ -162,15 +153,32 @@ nm_ip6_config_capture_resolv_conf (GArray *nameservers, changed = TRUE; } } - g_ptr_array_unref (read_ns); + + if (dns_options) { + read_options = nm_utils_read_resolv_conf_dns_options (rc_contents); + if (!read_options) + return changed; + + for (i = 0; i < read_options->len; i++) { + const char *s = g_ptr_array_index (read_options, i); + + if (_nm_utils_dns_option_validate (s, NULL, NULL, TRUE, _nm_utils_dns_option_descs) && + _nm_utils_dns_option_find_idx (dns_options, s) < 0) { + g_ptr_array_add (dns_options, g_strdup (s)); + changed = TRUE; + } + } + g_ptr_array_unref (read_options); + } + return changed; } static gboolean -addresses_are_duplicate (const NMPlatformIP6Address *a, const NMPlatformIP6Address *b, gboolean consider_plen) +addresses_are_duplicate (const NMPlatformIP6Address *a, const NMPlatformIP6Address *b) { - return IN6_ARE_ADDR_EQUAL (&a->address, &b->address) && (!consider_plen || a->plen == b->plen); + return IN6_ARE_ADDR_EQUAL (&a->address, &b->address); } static gboolean @@ -305,7 +313,7 @@ nm_ip6_config_capture (int ifindex, gboolean capture_resolv_conf, NMSettingIP6Co if (nm_platform_link_get_master (NM_PLATFORM_GET, ifindex) > 0) return NULL; - config = nm_ip6_config_new (); + config = nm_ip6_config_new (ifindex); priv = NM_IP6_CONFIG_GET_PRIVATE (config); g_array_unref (priv->addresses); @@ -356,7 +364,9 @@ nm_ip6_config_capture (int ifindex, gboolean capture_resolv_conf, NMSettingIP6Co * nameservers from /etc/resolv.conf. */ if (priv->addresses->len && has_gateway && capture_resolv_conf) - notify_nameservers = nm_ip6_config_capture_resolv_conf (priv->nameservers, NULL); + notify_nameservers = nm_ip6_config_capture_resolv_conf (priv->nameservers, + priv->dns_options, + NULL); g_array_sort_with_data (priv->addresses, _addresses_sort_cmp, GINT_TO_POINTER (use_temporary)); @@ -502,6 +512,12 @@ nm_ip6_config_merge_setting (NMIP6Config *config, NMSettingIPConfig *setting, gu for (i = 0; i < nsearches; i++) nm_ip6_config_add_search (config, nm_setting_ip_config_get_dns_search (setting, i)); + i = 0; + while ((i = nm_setting_ip_config_next_valid_dns_option (setting, i)) >= 0) { + nm_ip6_config_add_dns_option (config, nm_setting_ip_config_get_dns_option (setting, i)); + i++; + } + g_object_thaw_notify (G_OBJECT (config)); } @@ -510,7 +526,7 @@ nm_ip6_config_create_setting (const NMIP6Config *config) { NMSettingIPConfig *s_ip6; const struct in6_addr *gateway; - guint naddresses, nroutes, nnameservers, nsearches; + guint naddresses, nroutes, nnameservers, nsearches, noptions; const char *method = NULL; int i; gint64 route_metric; @@ -529,6 +545,7 @@ nm_ip6_config_create_setting (const NMIP6Config *config) nroutes = nm_ip6_config_get_num_routes (config); nnameservers = nm_ip6_config_get_num_nameservers (config); nsearches = nm_ip6_config_get_num_searches (config); + noptions = nm_ip6_config_get_num_dns_options (config); route_metric = nm_ip6_config_get_route_metric (config); /* Addresses */ @@ -611,6 +628,12 @@ nm_ip6_config_create_setting (const NMIP6Config *config) nm_setting_ip_config_add_dns_search (s_ip6, search); } + for (i = 0; i < noptions; i++) { + const char *option = nm_ip6_config_get_dns_option (config, i); + + nm_setting_ip_config_add_dns_option (s_ip6, option); + } + return NM_SETTING (s_ip6); } @@ -668,6 +691,12 @@ nm_ip6_config_merge (NMIP6Config *dst, const NMIP6Config *src, NMIPConfigMergeFl nm_ip6_config_add_search (dst, nm_ip6_config_get_search (src, i)); } + /* dns options */ + if (!NM_FLAGS_HAS (merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) { + for (i = 0; i < nm_ip6_config_get_num_dns_options (src); i++) + nm_ip6_config_add_dns_option (dst, nm_ip6_config_get_dns_option (src, i)); + } + if (nm_ip6_config_get_mss (src)) nm_ip6_config_set_mss (dst, nm_ip6_config_get_mss (src)); @@ -702,7 +731,7 @@ _addresses_get_index (const NMIP6Config *self, const NMPlatformIP6Address *addr) for (i = 0; i < priv->addresses->len; i++) { const NMPlatformIP6Address *a = &g_array_index (priv->addresses, NMPlatformIP6Address, i); - if (IN6_ARE_ADDR_EQUAL (&addr->address, &a->address)) + if (addresses_are_duplicate (a, addr)) return (int) i; } return -1; @@ -768,6 +797,21 @@ _searches_get_index (const NMIP6Config *self, const char *search) return -1; } +static int +_dns_options_get_index (const NMIP6Config *self, const char *option) +{ + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self); + guint i; + + for (i = 0; i < priv->dns_options->len; i++) { + const char *s = g_ptr_array_index (priv->dns_options, i); + + if (g_strcmp0 (option, s) == 0) + return (int) i; + } + return -1; +} + /*******************************************************************************/ /** @@ -835,6 +879,13 @@ nm_ip6_config_subtract (NMIP6Config *dst, const NMIP6Config *src) nm_ip6_config_del_search (dst, idx); } + /* dns options */ + for (i = 0; i < nm_ip6_config_get_num_dns_options (src); i++) { + idx = _dns_options_get_index (dst, nm_ip6_config_get_dns_option (src, i)); + if (idx >= 0) + nm_ip6_config_del_dns_option (dst, idx); + } + if (nm_ip6_config_get_mss (src) == nm_ip6_config_get_mss (dst)) nm_ip6_config_set_mss (dst, 0); @@ -886,6 +937,7 @@ nm_ip6_config_intersect (NMIP6Config *dst, const NMIP6Config *src) /* ignore domains */ /* ignore dns searches */ + /* ignome dns options */ g_object_thaw_notify (G_OBJECT (dst)); } @@ -907,7 +959,7 @@ nm_ip6_config_intersect (NMIP6Config *dst, const NMIP6Config *src) gboolean nm_ip6_config_replace (NMIP6Config *dst, const NMIP6Config *src, gboolean *relevant_changes) { -#ifndef G_DISABLE_ASSERT +#if NM_MORE_ASSERTS gboolean config_equal; #endif gboolean has_minor_changes = FALSE, has_relevant_changes = FALSE, are_equal; @@ -920,7 +972,7 @@ nm_ip6_config_replace (NMIP6Config *dst, const NMIP6Config *src, gboolean *relev g_return_val_if_fail (dst != NULL, FALSE); g_return_val_if_fail (src != dst, FALSE); -#ifndef G_DISABLE_ASSERT +#if NM_MORE_ASSERTS config_equal = nm_ip6_config_equal (dst, src); #endif @@ -929,6 +981,12 @@ nm_ip6_config_replace (NMIP6Config *dst, const NMIP6Config *src, gboolean *relev g_object_freeze_notify (G_OBJECT (dst)); + /* ifindex */ + if (src_priv->ifindex != dst_priv->ifindex) { + dst_priv->ifindex = src_priv->ifindex; + has_minor_changes = TRUE; + } + /* never_default */ if (src_priv->never_default != dst_priv->never_default) { dst_priv->never_default = src_priv->never_default; @@ -954,7 +1012,10 @@ nm_ip6_config_replace (NMIP6Config *dst, const NMIP6Config *src, gboolean *relev if (nm_platform_ip6_address_cmp (src_addr = nm_ip6_config_get_address (src, i), dst_addr = nm_ip6_config_get_address (dst, i))) { are_equal = FALSE; - if (!addresses_are_duplicate (src_addr, dst_addr, TRUE)) { + if ( !addresses_are_duplicate (src_addr, dst_addr) + || src_addr->plen != dst_addr->plen + || !IN6_ARE_ADDR_EQUAL (nm_platform_ip6_address_get_peer (src_addr), + nm_platform_ip6_address_get_peer (dst_addr))) { has_relevant_changes = TRUE; break; } @@ -1049,15 +1110,36 @@ nm_ip6_config_replace (NMIP6Config *dst, const NMIP6Config *src, gboolean *relev has_relevant_changes = TRUE; } + /* dns options */ + num = nm_ip6_config_get_num_dns_options (src); + are_equal = num == nm_ip6_config_get_num_dns_options (dst); + if (are_equal) { + for (i = 0; i < num; i++ ) { + if (g_strcmp0 (nm_ip6_config_get_dns_option (src, i), + nm_ip6_config_get_dns_option (dst, i))) { + are_equal = FALSE; + break; + } + } + } + if (!are_equal) { + nm_ip6_config_reset_dns_options (dst); + for (i = 0; i < num; i++) + nm_ip6_config_add_dns_option (dst, nm_ip6_config_get_dns_option (src, i)); + has_relevant_changes = TRUE; + } + /* mss */ if (src_priv->mss != dst_priv->mss) { nm_ip6_config_set_mss (dst, src_priv->mss); has_minor_changes = TRUE; } +#if NM_MORE_ASSERTS /* config_equal does not compare *all* the fields, therefore, we might have has_minor_changes * regardless of config_equal. But config_equal must correspond to has_relevant_changes. */ - g_assert (config_equal == !has_relevant_changes); + nm_assert (config_equal == !has_relevant_changes); +#endif g_object_thaw_notify (G_OBJECT (dst)); @@ -1078,13 +1160,13 @@ nm_ip6_config_dump (const NMIP6Config *config, const char *detail) g_message ("--------- NMIP6Config %p (%s)", config, detail); - str = nm_ip6_config_get_dbus_path (config); + str = nm_exported_object_get_path (NM_EXPORTED_OBJECT (config)); if (str) g_message (" path: %s", str); /* addresses */ for (i = 0; i < nm_ip6_config_get_num_addresses (config); i++) - g_message (" a: %s", nm_platform_ip6_address_to_string (nm_ip6_config_get_address (config, i))); + g_message (" a: %s", nm_platform_ip6_address_to_string (nm_ip6_config_get_address (config, i), NULL, 0)); /* default gateway */ tmp = nm_ip6_config_get_gateway (config); @@ -1099,7 +1181,7 @@ nm_ip6_config_dump (const NMIP6Config *config, const char *detail) /* routes */ for (i = 0; i < nm_ip6_config_get_num_routes (config); i++) - g_message (" rt: %s", nm_platform_ip6_route_to_string (nm_ip6_config_get_route (config, i))); + g_message (" rt: %s", nm_platform_ip6_route_to_string (nm_ip6_config_get_route (config, i), NULL, 0)); /* domains */ for (i = 0; i < nm_ip6_config_get_num_domains (config); i++) @@ -1109,6 +1191,10 @@ nm_ip6_config_dump (const NMIP6Config *config, const char *detail) for (i = 0; i < nm_ip6_config_get_num_searches (config); i++) g_message (" search: %s", nm_ip6_config_get_search (config, i)); + /* dns options */ + for (i = 0; i < nm_ip6_config_get_num_dns_options (config); i++) + g_message (" dnsopt: %s", nm_ip6_config_get_dns_option (config, i)); + g_message (" mss: %"G_GUINT32_FORMAT, nm_ip6_config_get_mss (config)); g_message (" n-dflt: %d", nm_ip6_config_get_never_default (config)); } @@ -1200,7 +1286,7 @@ nm_ip6_config_add_address (NMIP6Config *config, const NMPlatformIP6Address *new) for (i = 0; i < priv->addresses->len; i++ ) { NMPlatformIP6Address *item = &g_array_index (priv->addresses, NMPlatformIP6Address, i); - if (IN6_ARE_ADDR_EQUAL (&item->address, &new->address)) { + if (addresses_are_duplicate (item, new)) { if (nm_platform_ip6_address_cmp (item, new) == 0) return; @@ -1267,17 +1353,7 @@ gboolean nm_ip6_config_address_exists (const NMIP6Config *config, const NMPlatformIP6Address *needle) { - NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); - guint i; - - for (i = 0; i < priv->addresses->len; i++) { - const NMPlatformIP6Address *haystack = &g_array_index (priv->addresses, NMPlatformIP6Address, i); - - if ( IN6_ARE_ADDR_EQUAL (&needle->address, &haystack->address) - && needle->plen == haystack->plen) - return TRUE; - } - return FALSE; + return _addresses_get_index (config, needle) >= 0; } /******************************************************************/ @@ -1313,6 +1389,7 @@ nm_ip6_config_add_route (NMIP6Config *config, const NMPlatformIP6Route *new) g_return_if_fail (new != NULL); g_return_if_fail (new->plen > 0); + g_assert (priv->ifindex); for (i = 0; i < priv->routes->len; i++ ) { NMPlatformIP6Route *item = &g_array_index (priv->routes, NMPlatformIP6Route, i); @@ -1324,11 +1401,13 @@ nm_ip6_config_add_route (NMIP6Config *config, const NMPlatformIP6Route *new) *item = *new; /* Restore highest priority source */ item->source = MAX (old_source, new->source); + item->ifindex = priv->ifindex; goto NOTIFY; } } g_array_append_val (priv->routes, *new); + g_array_index (priv->routes, NMPlatformIP6Route, priv->routes->len - 1).ifindex = priv->ifindex; NOTIFY: _NOTIFY (config, PROP_ROUTE_DATA); _NOTIFY (config, PROP_ROUTES); @@ -1612,6 +1691,63 @@ nm_ip6_config_get_search (const NMIP6Config *config, guint i) /******************************************************************/ void +nm_ip6_config_reset_dns_options (NMIP6Config *config) +{ + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); + + if (priv->dns_options->len != 0) { + g_ptr_array_set_size (priv->dns_options, 0); + _NOTIFY (config, PROP_DNS_OPTIONS); + } +} + +void +nm_ip6_config_add_dns_option (NMIP6Config *config, const char *new) +{ + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); + int i; + + g_return_if_fail (new != NULL); + g_return_if_fail (new[0] != '\0'); + + for (i = 0; i < priv->dns_options->len; i++) + if (!g_strcmp0 (g_ptr_array_index (priv->dns_options, i), new)) + return; + + g_ptr_array_add (priv->dns_options, g_strdup (new)); + _NOTIFY (config, PROP_DNS_OPTIONS); +} + +void +nm_ip6_config_del_dns_option (NMIP6Config *config, guint i) +{ + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); + + g_return_if_fail (i < priv->dns_options->len); + + g_ptr_array_remove_index (priv->dns_options, i); + _NOTIFY (config, PROP_DNS_OPTIONS); +} + +guint32 +nm_ip6_config_get_num_dns_options (const NMIP6Config *config) +{ + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); + + return priv->dns_options->len; +} + +const char * +nm_ip6_config_get_dns_option (const NMIP6Config *config, guint i) +{ + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); + + return g_ptr_array_index (priv->dns_options, i); +} + +/******************************************************************/ + +void nm_ip6_config_set_mss (NMIP6Config *config, guint32 mss) { NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); @@ -1685,6 +1821,12 @@ nm_ip6_config_hash (const NMIP6Config *config, GChecksum *sum, gboolean dns_only s = nm_ip6_config_get_search (config, i); g_checksum_update (sum, (const guint8 *) s, strlen (s)); } + + for (i = 0; i < nm_ip6_config_get_num_dns_options (config); i++) { + s = nm_ip6_config_get_dns_option (config, i); + g_checksum_update (sum, (const guint8 *) s, strlen (s)); + } + } /** @@ -1732,28 +1874,32 @@ nm_ip6_config_equal (const NMIP6Config *a, const NMIP6Config *b) static void nm_ip6_config_init (NMIP6Config *config) { - NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); + NMIP6ConfigPrivate *priv; + + priv = G_TYPE_INSTANCE_GET_PRIVATE (config, NM_TYPE_IP6_CONFIG, NMIP6ConfigPrivate); + config->priv = priv; priv->addresses = g_array_new (FALSE, TRUE, sizeof (NMPlatformIP6Address)); priv->routes = g_array_new (FALSE, TRUE, sizeof (NMPlatformIP6Route)); priv->nameservers = g_array_new (FALSE, TRUE, sizeof (struct in6_addr)); priv->domains = g_ptr_array_new_with_free_func (g_free); priv->searches = g_ptr_array_new_with_free_func (g_free); + priv->dns_options = g_ptr_array_new_with_free_func (g_free); priv->route_metric = -1; } static void finalize (GObject *object) { - NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (object); - - g_free (priv->path); + NMIP6Config *self = NM_IP6_CONFIG (object); + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self); g_array_unref (priv->addresses); g_array_unref (priv->routes); g_array_unref (priv->nameservers); g_ptr_array_unref (priv->domains); g_ptr_array_unref (priv->searches); + g_ptr_array_unref (priv->dns_options); G_OBJECT_CLASS (nm_ip6_config_parent_class)->finalize (object); } @@ -1761,31 +1907,21 @@ finalize (GObject *object) static void nameservers_to_gvalue (GArray *array, GValue *value) { - GPtrArray *dns; + GVariantBuilder builder; guint i = 0; - dns = g_ptr_array_new (); + g_variant_builder_init (&builder, G_VARIANT_TYPE ("aay")); while (array && (i < array->len)) { struct in6_addr *addr; - GByteArray *bytearray; - addr = &g_array_index (array, struct in6_addr, i++); - bytearray = g_byte_array_sized_new (16); - g_byte_array_append (bytearray, (guint8 *) addr->s6_addr, 16); - g_ptr_array_add (dns, bytearray); + addr = &g_array_index (array, struct in6_addr, i++); + g_variant_builder_add (&builder, "@ay", + g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, + addr, 16, 1)); } - g_value_take_boxed (value, dns); -} - -static void -gvalue_destroy (gpointer data) -{ - GValue *value = (GValue *) data; - - g_value_unset (value); - g_slice_free (GValue, value); + g_value_take_variant (value, g_variant_builder_end (&builder)); } static void @@ -1793,168 +1929,123 @@ get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { NMIP6Config *config = NM_IP6_CONFIG (object); - NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (object); + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); switch (prop_id) { + case PROP_IFINDEX: + g_value_set_int (value, priv->ifindex); + break; case PROP_ADDRESS_DATA: { - GPtrArray *addresses = g_ptr_array_new (); + GVariantBuilder array_builder, addr_builder; int naddr = nm_ip6_config_get_num_addresses (config); int i; + g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("aa{sv}")); for (i = 0; i < naddr; i++) { const NMPlatformIP6Address *address = nm_ip6_config_get_address (config, i); - GHashTable *addr_hash; - GValue *val; - - addr_hash = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, gvalue_destroy); - - val = g_slice_new0 (GValue); - g_value_init (val, G_TYPE_STRING); - g_value_set_string (val, nm_utils_inet6_ntop (&address->address, NULL)); - g_hash_table_insert (addr_hash, "address", val); - val = g_slice_new0 (GValue); - g_value_init (val, G_TYPE_UINT); - g_value_set_uint (val, address->plen); - g_hash_table_insert (addr_hash, "prefix", val); + g_variant_builder_init (&addr_builder, G_VARIANT_TYPE ("a{sv}")); + g_variant_builder_add (&addr_builder, "{sv}", + "address", + g_variant_new_string (nm_utils_inet6_ntop (&address->address, NULL))); + g_variant_builder_add (&addr_builder, "{sv}", + "prefix", + g_variant_new_uint32 (address->plen)); + if ( !IN6_IS_ADDR_UNSPECIFIED (&address->peer_address) + && !IN6_ARE_ADDR_EQUAL (&address->peer_address, &address->address)) { + g_variant_builder_add (&addr_builder, "{sv}", + "peer", + g_variant_new_string (nm_utils_inet6_ntop (&address->peer_address, NULL))); + } - g_ptr_array_add (addresses, addr_hash); + g_variant_builder_add (&array_builder, "a{sv}", &addr_builder); } - g_value_take_boxed (value, addresses); + g_value_take_variant (value, g_variant_builder_end (&array_builder)); } break; case PROP_ADDRESSES: { - GPtrArray *addresses = g_ptr_array_new (); + GVariantBuilder array_builder; const struct in6_addr *gateway = nm_ip6_config_get_gateway (config); int naddr = nm_ip6_config_get_num_addresses (config); int i; + g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("a(ayuay)")); for (i = 0; i < naddr; i++) { const NMPlatformIP6Address *address = nm_ip6_config_get_address (config, i); - GValueArray *array = g_value_array_new (3); - GValue element = G_VALUE_INIT; - GByteArray *ba; - - /* IP address */ - g_value_init (&element, DBUS_TYPE_G_UCHAR_ARRAY); - ba = g_byte_array_new (); - g_byte_array_append (ba, (guint8 *) &address->address, 16); - g_value_take_boxed (&element, ba); - g_value_array_append (array, &element); - g_value_unset (&element); - - /* Prefix */ - g_value_init (&element, G_TYPE_UINT); - g_value_set_uint (&element, address->plen); - g_value_array_append (array, &element); - g_value_unset (&element); - - /* Gateway */ - g_value_init (&element, DBUS_TYPE_G_UCHAR_ARRAY); - ba = g_byte_array_new (); - g_byte_array_append (ba, (guint8 *) (i == 0 && gateway ? gateway : &in6addr_any), sizeof (*gateway)); - g_value_take_boxed (&element, ba); - g_value_array_append (array, &element); - g_value_unset (&element); - - g_ptr_array_add (addresses, array); + g_variant_builder_add (&array_builder, "(@ayu@ay)", + g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, + &address->address, 16, 1), + address->plen, + g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, + (i == 0 && gateway ? gateway : &in6addr_any), + 16, 1)); } - g_value_take_boxed (value, addresses); + g_value_take_variant (value, g_variant_builder_end (&array_builder)); } break; case PROP_ROUTE_DATA: { - GPtrArray *routes = g_ptr_array_new (); + GVariantBuilder array_builder, route_builder; guint nroutes = nm_ip6_config_get_num_routes (config); int i; + g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("aa{sv}")); for (i = 0; i < nroutes; i++) { const NMPlatformIP6Route *route = nm_ip6_config_get_route (config, i); - GHashTable *route_hash; - GValue *val; - - route_hash = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, gvalue_destroy); - - val = g_slice_new0 (GValue); - g_value_init (val, G_TYPE_STRING); - g_value_set_string (val, nm_utils_inet6_ntop (&route->network, NULL)); - g_hash_table_insert (route_hash, "dest", val); - - val = g_slice_new0 (GValue); - g_value_init (val, G_TYPE_UINT); - g_value_set_uint (val, route->plen); - g_hash_table_insert (route_hash, "prefix", val); + g_variant_builder_init (&route_builder, G_VARIANT_TYPE ("a{sv}")); + g_variant_builder_add (&route_builder, "{sv}", + "dest", + g_variant_new_string (nm_utils_inet6_ntop (&route->network, NULL))); + g_variant_builder_add (&route_builder, "{sv}", + "prefix", + g_variant_new_uint32 (route->plen)); if (!IN6_IS_ADDR_UNSPECIFIED (&route->gateway)) { - val = g_slice_new0 (GValue); - g_value_init (val, G_TYPE_STRING); - g_value_set_string (val, nm_utils_inet6_ntop (&route->gateway, NULL)); - g_hash_table_insert (route_hash, "next-hop", val); + g_variant_builder_add (&route_builder, "{sv}", + "next-hop", + g_variant_new_string (nm_utils_inet6_ntop (&route->gateway, NULL))); } - val = g_slice_new0 (GValue); - g_value_init (val, G_TYPE_UINT); - g_value_set_uint (val, route->metric); - g_hash_table_insert (route_hash, "metric", val); + g_variant_builder_add (&route_builder, "{sv}", + "metric", + g_variant_new_uint32 (route->metric)); - g_ptr_array_add (routes, route_hash); + g_variant_builder_add (&array_builder, "a{sv}", &route_builder); } - g_value_take_boxed (value, routes); + g_value_take_variant (value, g_variant_builder_end (&array_builder)); } break; case PROP_ROUTES: { - GPtrArray *routes = g_ptr_array_new (); + GVariantBuilder array_builder; int nroutes = nm_ip6_config_get_num_routes (config); int i; + g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("a(ayuayu)")); for (i = 0; i < nroutes; i++) { - GValueArray *array; const NMPlatformIP6Route *route = nm_ip6_config_get_route (config, i); - GByteArray *ba; - GValue element = G_VALUE_INIT; /* legacy versions of nm_ip6_route_set_prefix() in libnm-util assert that the * plen is positive. Skip the default routes not to break older clients. */ if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route)) continue; - array = g_value_array_new (4); - - g_value_init (&element, DBUS_TYPE_G_UCHAR_ARRAY); - ba = g_byte_array_new (); - g_byte_array_append (ba, (guint8 *) &route->network, sizeof (route->network)); - g_value_take_boxed (&element, ba); - g_value_array_append (array, &element); - g_value_unset (&element); - - g_value_init (&element, G_TYPE_UINT); - g_value_set_uint (&element, route->plen); - g_value_array_append (array, &element); - g_value_unset (&element); - - g_value_init (&element, DBUS_TYPE_G_UCHAR_ARRAY); - ba = g_byte_array_new (); - g_byte_array_append (ba, (guint8 *) &route->gateway, sizeof (route->gateway)); - g_value_take_boxed (&element, ba); - g_value_array_append (array, &element); - g_value_unset (&element); - - g_value_init (&element, G_TYPE_UINT); - g_value_set_uint (&element, route->metric); - g_value_array_append (array, &element); - g_value_unset (&element); - - g_ptr_array_add (routes, array); + g_variant_builder_add (&array_builder, "(@ayu@ayu)", + g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, + &route->network, 16, 1), + (guint32) route->plen, + g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, + &route->gateway, 16, 1), + (guint32) route->metric); } - g_value_take_boxed (value, routes); + g_value_take_variant (value, g_variant_builder_end (&array_builder)); } break; case PROP_GATEWAY: @@ -1967,10 +2058,32 @@ get_property (GObject *object, guint prop_id, nameservers_to_gvalue (priv->nameservers, value); break; case PROP_DOMAINS: - g_value_set_boxed (value, priv->domains); + nm_utils_g_value_set_strv (value, priv->domains); break; case PROP_SEARCHES: - g_value_set_boxed (value, priv->searches); + nm_utils_g_value_set_strv (value, priv->searches); + break; + case PROP_DNS_OPTIONS: + nm_utils_g_value_set_strv (value, priv->dns_options); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + NMIP6Config *config = NM_IP6_CONFIG (object); + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); + + switch (prop_id) { + case PROP_IFINDEX: + priv->ifindex = g_value_get_int (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -1982,58 +2095,78 @@ static void nm_ip6_config_class_init (NMIP6ConfigClass *config_class) { GObjectClass *object_class = G_OBJECT_CLASS (config_class); + NMExportedObjectClass *exported_object_class = NM_EXPORTED_OBJECT_CLASS (config_class); g_type_class_add_private (config_class, sizeof (NMIP6ConfigPrivate)); + exported_object_class->export_path = NM_DBUS_PATH "/IP6Config/%u"; + /* virtual methods */ object_class->get_property = get_property; + object_class->set_property = set_property; object_class->finalize = finalize; /* properties */ + obj_properties[PROP_IFINDEX] = + g_param_spec_int (NM_IP6_CONFIG_IFINDEX, "", "", + -1, G_MAXINT, -1, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); 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); + g_param_spec_variant (NM_IP6_CONFIG_ADDRESS_DATA, "", "", + G_VARIANT_TYPE ("aa{sv}"), + 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, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); + g_param_spec_variant (NM_IP6_CONFIG_ADDRESSES, "", "", + G_VARIANT_TYPE ("a(ayuay)"), + NULL, + 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); + g_param_spec_variant (NM_IP6_CONFIG_ROUTE_DATA, "", "", + G_VARIANT_TYPE ("aa{sv}"), + NULL, + 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); + g_param_spec_variant (NM_IP6_CONFIG_ROUTES, "", "", + G_VARIANT_TYPE ("a(ayuayu)"), + NULL, + 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, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); + g_param_spec_variant (NM_IP6_CONFIG_NAMESERVERS, "", "", + G_VARIANT_TYPE ("aay"), + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); obj_properties[PROP_DOMAINS] = - g_param_spec_boxed (NM_IP6_CONFIG_DOMAINS, "", "", - DBUS_TYPE_G_ARRAY_OF_STRING, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); + g_param_spec_boxed (NM_IP6_CONFIG_DOMAINS, "", "", + G_TYPE_STRV, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); obj_properties[PROP_SEARCHES] = - g_param_spec_boxed (NM_IP6_CONFIG_SEARCHES, "", "", - DBUS_TYPE_G_ARRAY_OF_STRING, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); + g_param_spec_boxed (NM_IP6_CONFIG_SEARCHES, "", "", + G_TYPE_STRV, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_DNS_OPTIONS] = + g_param_spec_boxed (NM_IP6_CONFIG_DNS_OPTIONS, "", "", + G_TYPE_STRV, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, LAST_PROP, obj_properties); - nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), - G_TYPE_FROM_CLASS (config_class), - &dbus_glib_nm_ip6_config_object_info); + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (config_class), + NMDBUS_TYPE_IP6_CONFIG_SKELETON, + NULL); } |