diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index ed028971f1..ac840ab931 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -4813,8 +4813,6 @@ END_ADD_DEFAULT_ROUTE: priv->default_route.v4_has = _device_get_default_route_from_platform (self, AF_INET, (NMPlatformIPRoute *) &priv->default_route.v4); } - nm_ip4_config_addresses_sort (composite); - /* Allow setting MTU etc */ if (commit) { if (NM_DEVICE_GET_CLASS (self)->ip4_config_pre_commit) @@ -5434,13 +5432,15 @@ ip6_config_merge_and_apply (NMDevice *self, /* If no config was passed in, create a new one */ composite = nm_ip6_config_new (nm_device_get_ip_ifindex (self)); + nm_ip6_config_set_privacy (composite, + priv->rdisc ? + priv->rdisc_use_tempaddr : + NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN); init_ip6_config_dns_priority (self, composite); if (commit) ensure_con_ip6_config (self); - g_assert (composite); - /* Merge all the IP configs into the composite config */ if (priv->ac_ip6_config) { nm_ip6_config_merge (composite, priv->ac_ip6_config, @@ -5567,9 +5567,6 @@ END_ADD_DEFAULT_ROUTE: priv->default_route.v6_has = _device_get_default_route_from_platform (self, AF_INET6, (NMPlatformIPRoute *) &priv->default_route.v6); } - nm_ip6_config_addresses_sort (composite, - priv->rdisc ? priv->rdisc_use_tempaddr : NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN); - /* Allow setting MTU etc */ if (commit) { NMUtilsIPv6IfaceId iid; diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c index a4d4361248..7b42235985 100644 --- a/src/nm-ip4-config.c +++ b/src/nm-ip4-config.c @@ -55,6 +55,8 @@ typedef struct { gint64 route_metric; gboolean metered; gint dns_priority; + GVariant *address_data_variant; + GVariant *addresses_variant; } NMIP4ConfigPrivate; struct _NMIP4Config { @@ -207,8 +209,9 @@ _addresses_sort_cmp_get_prio (in_addr_t addr) static gint _addresses_sort_cmp (gconstpointer a, gconstpointer b) { - gint p1, p2, c; + gint p1, p2; const NMPlatformIP4Address *a1 = a, *a2 = b; + guint32 n1, n2; /* Sort by address type. For example link local will * be sorted *after* a global address. */ @@ -224,43 +227,30 @@ _addresses_sort_cmp (gconstpointer a, gconstpointer b) if ((a1->label[0] == '\0') != (a2->label[0] == '\0')) return (a1->label[0] == '\0') ? -1 : 1; - /* finally sort addresses lexically */ - c = memcmp (&a1->address, &a2->address, sizeof (a2->address)); - return c != 0 ? c : memcmp (a1, a2, sizeof (*a1)); -} + /* Finally, sort addresses lexically. We compare only the + * network part so that the order of addresses in the same + * subnet (and thus also the primary/secondary role) is + * preserved. + */ + n1 = a1->address & nm_utils_ip4_prefix_to_netmask (a1->plen); + n2 = a2->address & nm_utils_ip4_prefix_to_netmask (a2->plen); -gboolean -nm_ip4_config_addresses_sort (NMIP4Config *self) -{ - NMIP4ConfigPrivate *priv; - size_t data_len = 0; - char *data_pre = NULL; - gboolean changed; - - g_return_val_if_fail (NM_IS_IP4_CONFIG (self), FALSE); - - priv = NM_IP4_CONFIG_GET_PRIVATE (self); - if (priv->addresses->len > 1) { - data_len = priv->addresses->len * g_array_get_element_size (priv->addresses); - data_pre = g_new (char, data_len); - memcpy (data_pre, priv->addresses->data, data_len); - - g_array_sort (priv->addresses, _addresses_sort_cmp); - - changed = memcmp (data_pre, priv->addresses->data, data_len) != 0; - g_free (data_pre); - - if (changed) { - _notify (self, PROP_ADDRESS_DATA); - _notify (self, PROP_ADDRESSES); - return TRUE; - } - } - return FALSE; + return memcmp (&n1, &n2, sizeof (guint32)); } /*****************************************************************************/ +static void +notify_addresses (NMIP4Config *self) +{ + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self); + + nm_clear_g_variant (&priv->address_data_variant); + nm_clear_g_variant (&priv->addresses_variant); + _notify (self, PROP_ADDRESS_DATA); + _notify (self, PROP_ADDRESSES); +} + NMIP4Config * nm_ip4_config_capture (int ifindex, gboolean capture_resolv_conf) { @@ -347,7 +337,6 @@ gboolean nm_ip4_config_commit (const NMIP4Config *config, int ifindex, gboolean routes_full_sync, gint64 default_route_metric) { const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); - int i; gs_unref_ptrarray GPtrArray *added_addresses = NULL; g_return_val_if_fail (ifindex > 0, FALSE); @@ -359,7 +348,8 @@ nm_ip4_config_commit (const NMIP4Config *config, int ifindex, gboolean routes_fu /* Routes */ { - int count = nm_ip4_config_get_num_routes (config); + guint i; + guint count = nm_ip4_config_get_num_routes (config); GArray *routes = g_array_sized_new (FALSE, FALSE, sizeof (NMPlatformIP4Route), count); gboolean success; gs_unref_array GArray *device_route_purge_list = NULL; @@ -1366,7 +1356,7 @@ gboolean nm_ip4_config_destination_is_direct (const NMIP4Config *config, guint32 network, guint8 plen) { guint naddresses = nm_ip4_config_get_num_addresses (config); - int i; + guint i; in_addr_t peer_network; for (i = 0; i < naddresses; i++) { @@ -1473,8 +1463,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); + notify_addresses (config); } } @@ -1531,8 +1520,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); + notify_addresses (config); } void @@ -1543,8 +1531,8 @@ 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); + + notify_addresses (config); } guint @@ -1725,7 +1713,7 @@ nm_ip4_config_del_nameserver (NMIP4Config *config, guint i) _notify (config, PROP_NAMESERVERS); } -guint32 +guint nm_ip4_config_get_num_nameservers (const NMIP4Config *config) { const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); @@ -1782,7 +1770,7 @@ nm_ip4_config_del_domain (NMIP4Config *config, guint i) _notify (config, PROP_DOMAINS); } -guint32 +guint nm_ip4_config_get_num_domains (const NMIP4Config *config) { const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); @@ -1854,7 +1842,7 @@ nm_ip4_config_del_search (NMIP4Config *config, guint i) _notify (config, PROP_SEARCHES); } -guint32 +guint nm_ip4_config_get_num_searches (const NMIP4Config *config) { const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); @@ -1911,7 +1899,7 @@ nm_ip4_config_del_dns_option(NMIP4Config *config, guint i) _notify (config, PROP_DNS_OPTIONS); } -guint32 +guint nm_ip4_config_get_num_dns_options (const NMIP4Config *config) { const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); @@ -1999,7 +1987,7 @@ nm_ip4_config_del_nis_server (NMIP4Config *config, guint i) g_array_remove_index (priv->nis, i); } -guint32 +guint nm_ip4_config_get_num_nis_servers (const NMIP4Config *config) { const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); @@ -2072,7 +2060,7 @@ nm_ip4_config_del_wins (NMIP4Config *config, guint i) _notify (config, PROP_WINS_SERVERS); } -guint32 +guint nm_ip4_config_get_num_wins (const NMIP4Config *config) { const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); @@ -2147,7 +2135,7 @@ hash_u32 (GChecksum *sum, guint32 n) void nm_ip4_config_hash (const NMIP4Config *config, GChecksum *sum, gboolean dns_only) { - guint32 i; + guint i; const char *s; g_return_if_fail (config); @@ -2267,6 +2255,8 @@ finalize (GObject *object) NMIP4Config *self = NM_IP4_CONFIG (object); NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self); + nm_clear_g_variant (&priv->address_data_variant); + nm_clear_g_variant (&priv->addresses_variant); g_array_unref (priv->addresses); g_array_unref (priv->routes); g_array_unref (priv->nameservers); @@ -2292,14 +2282,26 @@ get_property (GObject *object, guint prop_id, g_value_set_int (value, priv->ifindex); break; case PROP_ADDRESS_DATA: + case PROP_ADDRESSES: { GVariantBuilder array_builder, addr_builder; - int naddr = nm_ip4_config_get_num_addresses (config); - int i; + gs_unref_array GArray *new = NULL; + guint naddr, i; + g_return_if_fail (!!priv->address_data_variant == !!priv->addresses_variant); + + if (priv->address_data_variant) + goto return_cached; + + naddr = nm_ip4_config_get_num_addresses (config); + new = g_array_sized_new (FALSE, FALSE, sizeof (NMPlatformIP4Address), naddr); + g_array_append_vals (new, priv->addresses->data, priv->addresses->len); + g_array_sort (new, _addresses_sort_cmp); + + /* Build address data variant */ g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("aa{sv}")); for (i = 0; i < naddr; i++) { - const NMPlatformIP4Address *address = nm_ip4_config_get_address (config, i); + const NMPlatformIP4Address *address = &g_array_index (new, NMPlatformIP4Address, i); g_variant_builder_init (&addr_builder, G_VARIANT_TYPE ("a{sv}")); g_variant_builder_add (&addr_builder, "{sv}", @@ -2322,19 +2324,12 @@ get_property (GObject *object, guint prop_id, g_variant_builder_add (&array_builder, "a{sv}", &addr_builder); } + priv->address_data_variant = g_variant_ref_sink (g_variant_builder_end (&array_builder)); - g_value_take_variant (value, g_variant_builder_end (&array_builder)); - } - break; - case PROP_ADDRESSES: - { - GVariantBuilder array_builder; - int naddr = nm_ip4_config_get_num_addresses (config); - int i; - + /* Build addresses variant */ g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("aau")); for (i = 0; i < naddr; i++) { - const NMPlatformIP4Address *address = nm_ip4_config_get_address (config, i); + const NMPlatformIP4Address *address = &g_array_index (new, NMPlatformIP4Address, i); guint32 dbus_addr[3]; dbus_addr[0] = address->address; @@ -2345,15 +2340,20 @@ get_property (GObject *object, guint prop_id, g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32, dbus_addr, 3, sizeof (guint32))); } + priv->addresses_variant = g_variant_ref_sink (g_variant_builder_end (&array_builder)); - g_value_take_variant (value, g_variant_builder_end (&array_builder)); +return_cached: + g_value_set_variant (value, + prop_id == PROP_ADDRESS_DATA ? + priv->address_data_variant : + priv->addresses_variant); } break; case PROP_ROUTE_DATA: { GVariantBuilder array_builder, route_builder; guint nroutes = nm_ip4_config_get_num_routes (config); - int i; + guint i; g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("aa{sv}")); for (i = 0; i < nroutes; i++) { @@ -2385,7 +2385,7 @@ get_property (GObject *object, guint prop_id, { GVariantBuilder array_builder; guint nroutes = nm_ip4_config_get_num_routes (config); - int i; + guint i; g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("aau")); for (i = 0; i < nroutes; i++) { diff --git a/src/nm-ip4-config.h b/src/nm-ip4-config.h index f302630a0c..6fc45dc2e7 100644 --- a/src/nm-ip4-config.h +++ b/src/nm-ip4-config.h @@ -58,13 +58,13 @@ NMIP4Config * nm_ip4_config_new (int ifindex); int nm_ip4_config_get_ifindex (const NMIP4Config *config); -/* Integration with nm-platform and nm-setting */ + NMIP4Config *nm_ip4_config_capture (int ifindex, gboolean capture_resolv_conf); gboolean nm_ip4_config_commit (const NMIP4Config *config, int ifindex, gboolean routes_full_sync, gint64 default_route_metric); void nm_ip4_config_merge_setting (NMIP4Config *config, NMSettingIPConfig *setting, guint32 default_route_metric); NMSetting *nm_ip4_config_create_setting (const NMIP4Config *config); -/* Utility functions */ + void nm_ip4_config_merge (NMIP4Config *dst, const NMIP4Config *src, NMIPConfigMergeFlags merge_flags); void nm_ip4_config_subtract (NMIP4Config *dst, const NMIP4Config *src); void nm_ip4_config_intersect (NMIP4Config *dst, const NMIP4Config *src); @@ -72,7 +72,7 @@ gboolean nm_ip4_config_replace (NMIP4Config *dst, const NMIP4Config *src, gboole gboolean nm_ip4_config_destination_is_direct (const NMIP4Config *config, guint32 dest, guint8 plen); void nm_ip4_config_dump (const NMIP4Config *config, const char *detail); -/* Gateways */ + void nm_ip4_config_set_never_default (NMIP4Config *config, gboolean never_default); gboolean nm_ip4_config_get_never_default (const NMIP4Config *config); void nm_ip4_config_set_gateway (NMIP4Config *config, guint32 gateway); @@ -81,82 +81,69 @@ gboolean nm_ip4_config_has_gateway (const NMIP4Config *config); guint32 nm_ip4_config_get_gateway (const NMIP4Config *config); gint64 nm_ip4_config_get_route_metric (const NMIP4Config *config); -/* Addresses */ void nm_ip4_config_reset_addresses (NMIP4Config *config); void nm_ip4_config_add_address (NMIP4Config *config, const NMPlatformIP4Address *address); void nm_ip4_config_del_address (NMIP4Config *config, guint i); guint nm_ip4_config_get_num_addresses (const NMIP4Config *config); const NMPlatformIP4Address *nm_ip4_config_get_address (const NMIP4Config *config, guint i); gboolean nm_ip4_config_address_exists (const NMIP4Config *config, const NMPlatformIP4Address *address); -gboolean nm_ip4_config_addresses_sort (NMIP4Config *config); -/* Routes */ void nm_ip4_config_reset_routes (NMIP4Config *config); void nm_ip4_config_add_route (NMIP4Config *config, const NMPlatformIP4Route *route); void nm_ip4_config_del_route (NMIP4Config *config, guint i); -guint32 nm_ip4_config_get_num_routes (const NMIP4Config *config); -const NMPlatformIP4Route *nm_ip4_config_get_route (const NMIP4Config *config, guint32 i); +guint nm_ip4_config_get_num_routes (const NMIP4Config *config); +const NMPlatformIP4Route *nm_ip4_config_get_route (const NMIP4Config *config, guint i); const NMPlatformIP4Route *nm_ip4_config_get_direct_route_for_host (const NMIP4Config *config, guint32 host); -/* Nameservers */ void nm_ip4_config_reset_nameservers (NMIP4Config *config); void nm_ip4_config_add_nameserver (NMIP4Config *config, guint32 nameserver); void nm_ip4_config_del_nameserver (NMIP4Config *config, guint i); -guint32 nm_ip4_config_get_num_nameservers (const NMIP4Config *config); +guint nm_ip4_config_get_num_nameservers (const NMIP4Config *config); guint32 nm_ip4_config_get_nameserver (const NMIP4Config *config, guint i); -/* Domains */ void nm_ip4_config_reset_domains (NMIP4Config *config); void nm_ip4_config_add_domain (NMIP4Config *config, const char *domain); void nm_ip4_config_del_domain (NMIP4Config *config, guint i); -guint32 nm_ip4_config_get_num_domains (const NMIP4Config *config); +guint nm_ip4_config_get_num_domains (const NMIP4Config *config); const char * nm_ip4_config_get_domain (const NMIP4Config *config, guint i); -/* Search lists */ void nm_ip4_config_reset_searches (NMIP4Config *config); void nm_ip4_config_add_search (NMIP4Config *config, const char *search); void nm_ip4_config_del_search (NMIP4Config *config, guint i); -guint32 nm_ip4_config_get_num_searches (const NMIP4Config *config); +guint nm_ip4_config_get_num_searches (const NMIP4Config *config); const char * nm_ip4_config_get_search (const NMIP4Config *config, guint i); -/* DNS options */ void nm_ip4_config_reset_dns_options (NMIP4Config *config); void nm_ip4_config_add_dns_option (NMIP4Config *config, const char *option); void nm_ip4_config_del_dns_option (NMIP4Config *config, guint i); -guint32 nm_ip4_config_get_num_dns_options (const NMIP4Config *config); +guint nm_ip4_config_get_num_dns_options (const NMIP4Config *config); const char * nm_ip4_config_get_dns_option (const NMIP4Config *config, guint i); -/* DNS priority */ void nm_ip4_config_set_dns_priority (NMIP4Config *config, gint priority); gint nm_ip4_config_get_dns_priority (const NMIP4Config *config); -/* MSS */ void nm_ip4_config_set_mss (NMIP4Config *config, guint32 mss); guint32 nm_ip4_config_get_mss (const NMIP4Config *config); -/* NIS */ void nm_ip4_config_reset_nis_servers (NMIP4Config *config); void nm_ip4_config_add_nis_server (NMIP4Config *config, guint32 nis); void nm_ip4_config_del_nis_server (NMIP4Config *config, guint i); -guint32 nm_ip4_config_get_num_nis_servers (const NMIP4Config *config); +guint nm_ip4_config_get_num_nis_servers (const NMIP4Config *config); guint32 nm_ip4_config_get_nis_server (const NMIP4Config *config, guint i); void nm_ip4_config_set_nis_domain (NMIP4Config *config, const char *domain); const char * nm_ip4_config_get_nis_domain (const NMIP4Config *config); -/* WINS */ void nm_ip4_config_reset_wins (NMIP4Config *config); void nm_ip4_config_add_wins (NMIP4Config *config, guint32 wins); void nm_ip4_config_del_wins (NMIP4Config *config, guint i); -guint32 nm_ip4_config_get_num_wins (const NMIP4Config *config); +guint nm_ip4_config_get_num_wins (const NMIP4Config *config); guint32 nm_ip4_config_get_wins (const NMIP4Config *config, guint i); -/* MTU */ void nm_ip4_config_set_mtu (NMIP4Config *config, guint32 mtu, NMIPConfigSource source); guint32 nm_ip4_config_get_mtu (const NMIP4Config *config); NMIPConfigSource nm_ip4_config_get_mtu_source (const NMIP4Config *config); -/* Metered */ void nm_ip4_config_set_metered (NMIP4Config *config, gboolean metered); gboolean nm_ip4_config_get_metered (const NMIP4Config *config); diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c index 8002d61a0a..a0211246cc 100644 --- a/src/nm-ip6-config.c +++ b/src/nm-ip6-config.c @@ -48,6 +48,9 @@ typedef struct { int ifindex; gint64 route_metric; gint dns_priority; + GVariant *address_data_variant; + GVariant *addresses_variant; + NMSettingIP6ConfigPrivacy privacy; } NMIP6ConfigPrivate; struct _NMIP6Config { @@ -104,7 +107,26 @@ nm_ip6_config_get_ifindex (const NMIP6Config *config) return NM_IP6_CONFIG_GET_PRIVATE (config)->ifindex; } -/******************************************************************/ +void +nm_ip6_config_set_privacy (NMIP6Config *config, NMSettingIP6ConfigPrivacy privacy) +{ + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); + + priv->privacy = privacy; +} + +/*****************************************************************************/ + +static void +notify_addresses (NMIP6Config *self) +{ + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self); + + nm_clear_g_variant (&priv->address_data_variant); + nm_clear_g_variant (&priv->addresses_variant); + _notify (self, PROP_ADDRESS_DATA); + _notify (self, PROP_ADDRESSES); +} /** * nm_ip6_config_capture_resolv_conf(): @@ -266,7 +288,7 @@ _addresses_sort_cmp (gconstpointer a, gconstpointer b, gpointer user_data) } gboolean -nm_ip6_config_addresses_sort (NMIP6Config *self, NMSettingIP6ConfigPrivacy use_temporary) +nm_ip6_config_addresses_sort (NMIP6Config *self) { NMIP6ConfigPrivate *priv; size_t data_len = 0; @@ -281,14 +303,14 @@ nm_ip6_config_addresses_sort (NMIP6Config *self, NMSettingIP6ConfigPrivacy use_t data_pre = g_new (char, data_len); memcpy (data_pre, priv->addresses->data, data_len); - g_array_sort_with_data (priv->addresses, _addresses_sort_cmp, GINT_TO_POINTER (use_temporary)); + g_array_sort_with_data (priv->addresses, _addresses_sort_cmp, + GINT_TO_POINTER (priv->privacy)); changed = memcmp (data_pre, priv->addresses->data, data_len) != 0; g_free (data_pre); if (changed) { - _notify (self, PROP_ADDRESS_DATA); - _notify (self, PROP_ADDRESSES); + notify_addresses (self); return TRUE; } } @@ -384,7 +406,6 @@ gboolean nm_ip6_config_commit (const NMIP6Config *config, int ifindex, gboolean routes_full_sync) { const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); - int i; gboolean success; g_return_val_if_fail (ifindex > 0, FALSE); @@ -395,7 +416,8 @@ nm_ip6_config_commit (const NMIP6Config *config, int ifindex, gboolean routes_fu /* Routes */ { - int count = nm_ip6_config_get_num_routes (config); + guint i; + guint count = nm_ip6_config_get_num_routes (config); GArray *routes = g_array_sized_new (FALSE, FALSE, sizeof (NMPlatformIP6Route), count); const NMPlatformIP6Route *route; @@ -712,8 +734,8 @@ nm_ip6_config_merge (NMIP6Config *dst, const NMIP6Config *src, NMIPConfigMergeFl gboolean nm_ip6_config_destination_is_direct (const NMIP6Config *config, const struct in6_addr *network, guint8 plen) { - int num = nm_ip6_config_get_num_addresses (config); - int i; + guint num = nm_ip6_config_get_num_addresses (config); + guint i; nm_assert (network); nm_assert (plen <= 128); @@ -1156,6 +1178,11 @@ nm_ip6_config_replace (NMIP6Config *dst, const NMIP6Config *src, gboolean *relev has_minor_changes = TRUE; } + if (src_priv->privacy != dst_priv->privacy) { + nm_ip6_config_set_privacy (dst, src_priv->privacy); + 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. */ @@ -1282,8 +1309,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); + notify_addresses (config); } } @@ -1340,8 +1366,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); +notify_addresses (config); } void @@ -1352,8 +1377,8 @@ 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); + + notify_addresses (config); } guint @@ -1626,7 +1651,7 @@ nm_ip6_config_del_nameserver (NMIP6Config *config, guint i) _notify (config, PROP_NAMESERVERS); } -guint32 +guint nm_ip6_config_get_num_nameservers (const NMIP6Config *config) { const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); @@ -1683,7 +1708,7 @@ nm_ip6_config_del_domain (NMIP6Config *config, guint i) _notify (config, PROP_DOMAINS); } -guint32 +guint nm_ip6_config_get_num_domains (const NMIP6Config *config) { const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); @@ -1755,7 +1780,7 @@ nm_ip6_config_del_search (NMIP6Config *config, guint i) _notify (config, PROP_SEARCHES); } -guint32 +guint nm_ip6_config_get_num_searches (const NMIP6Config *config) { const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); @@ -1812,7 +1837,7 @@ nm_ip6_config_del_dns_option (NMIP6Config *config, guint i) _notify (config, PROP_DNS_OPTIONS); } -guint32 +guint nm_ip6_config_get_num_dns_options (const NMIP6Config *config) { const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); @@ -2000,6 +2025,8 @@ finalize (GObject *object) g_ptr_array_unref (priv->domains); g_ptr_array_unref (priv->searches); g_ptr_array_unref (priv->dns_options); + nm_clear_g_variant (&priv->address_data_variant); + nm_clear_g_variant (&priv->addresses_variant); G_OBJECT_CLASS (nm_ip6_config_parent_class)->finalize (object); } @@ -2036,14 +2063,28 @@ get_property (GObject *object, guint prop_id, g_value_set_int (value, priv->ifindex); break; case PROP_ADDRESS_DATA: + case PROP_ADDRESSES: { GVariantBuilder array_builder, addr_builder; - int naddr = nm_ip6_config_get_num_addresses (config); - int i; + gs_unref_array GArray *new = NULL; + const struct in6_addr *gateway; + guint naddr, i; + + g_return_if_fail (!!priv->address_data_variant == !!priv->addresses_variant); + + if (priv->address_data_variant) + goto return_cached; + + naddr = nm_ip6_config_get_num_addresses (config); + gateway = nm_ip6_config_get_gateway (config); + new = g_array_sized_new (FALSE, FALSE, sizeof (NMPlatformIP6Address), naddr); + g_array_append_vals (new, priv->addresses->data, naddr); + g_array_sort_with_data (new, _addresses_sort_cmp, + GINT_TO_POINTER (priv->privacy)); 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); + const NMPlatformIP6Address *address = &g_array_index (new, NMPlatformIP6Address, i); g_variant_builder_init (&addr_builder, G_VARIANT_TYPE ("a{sv}")); g_variant_builder_add (&addr_builder, "{sv}", @@ -2061,20 +2102,11 @@ get_property (GObject *object, guint prop_id, g_variant_builder_add (&array_builder, "a{sv}", &addr_builder); } - - g_value_take_variant (value, g_variant_builder_end (&array_builder)); - } - break; - case PROP_ADDRESSES: - { - 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; + priv->address_data_variant = g_variant_ref_sink (g_variant_builder_end (&array_builder)); 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); + const NMPlatformIP6Address *address = &g_array_index (new, NMPlatformIP6Address, i); g_variant_builder_add (&array_builder, "(@ayu@ay)", g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, @@ -2085,7 +2117,12 @@ get_property (GObject *object, guint prop_id, 16, 1)); } - g_value_take_variant (value, g_variant_builder_end (&array_builder)); + priv->addresses_variant = g_variant_ref_sink (g_variant_builder_end (&array_builder)); +return_cached: + g_value_set_variant (value, + prop_id == PROP_ADDRESS_DATA ? + priv->address_data_variant : + priv->addresses_variant); } break; case PROP_ROUTE_DATA: diff --git a/src/nm-ip6-config.h b/src/nm-ip6-config.h index c3f8d9f879..9454c0f772 100644 --- a/src/nm-ip6-config.h +++ b/src/nm-ip6-config.h @@ -60,13 +60,13 @@ NMIP6Config * nm_ip6_config_new_cloned (const NMIP6Config *src); int nm_ip6_config_get_ifindex (const NMIP6Config *config); -/* Integration with nm-platform and nm-setting */ + NMIP6Config *nm_ip6_config_capture (int ifindex, gboolean capture_resolv_conf, NMSettingIP6ConfigPrivacy use_temporary); gboolean nm_ip6_config_commit (const NMIP6Config *config, int ifindex, gboolean routes_full_sync); void nm_ip6_config_merge_setting (NMIP6Config *config, NMSettingIPConfig *setting, guint32 default_route_metric); NMSetting *nm_ip6_config_create_setting (const NMIP6Config *config); -/* Utility functions */ + void nm_ip6_config_merge (NMIP6Config *dst, const NMIP6Config *src, NMIPConfigMergeFlags merge_flags); void nm_ip6_config_subtract (NMIP6Config *dst, const NMIP6Config *src); void nm_ip6_config_intersect (NMIP6Config *dst, const NMIP6Config *src); @@ -74,14 +74,13 @@ gboolean nm_ip6_config_replace (NMIP6Config *dst, const NMIP6Config *src, gboole int nm_ip6_config_destination_is_direct (const NMIP6Config *config, const struct in6_addr *dest, guint8 plen); void nm_ip6_config_dump (const NMIP6Config *config, const char *detail); -/* Gateways */ + void nm_ip6_config_set_never_default (NMIP6Config *config, gboolean never_default); gboolean nm_ip6_config_get_never_default (const NMIP6Config *config); void nm_ip6_config_set_gateway (NMIP6Config *config, const struct in6_addr *); const struct in6_addr *nm_ip6_config_get_gateway (const NMIP6Config *config); gint64 nm_ip6_config_get_route_metric (const NMIP6Config *config); -/* Addresses */ void nm_ip6_config_reset_addresses (NMIP6Config *config); void nm_ip6_config_add_address (NMIP6Config *config, const NMPlatformIP6Address *address); void nm_ip6_config_del_address (NMIP6Config *config, guint i); @@ -89,60 +88,54 @@ guint nm_ip6_config_get_num_addresses (const NMIP6Config *config); const NMPlatformIP6Address *nm_ip6_config_get_address (const NMIP6Config *config, guint i); const NMPlatformIP6Address *nm_ip6_config_get_address_first_nontentative (const NMIP6Config *config, gboolean linklocal); gboolean nm_ip6_config_address_exists (const NMIP6Config *config, const NMPlatformIP6Address *address); -gboolean nm_ip6_config_addresses_sort (NMIP6Config *config, NMSettingIP6ConfigPrivacy use_temporary); +gboolean nm_ip6_config_addresses_sort (NMIP6Config *config); gboolean nm_ip6_config_has_any_dad_pending (const NMIP6Config *self, const NMIP6Config *candidates); -/* Routes */ void nm_ip6_config_reset_routes (NMIP6Config *config); void nm_ip6_config_add_route (NMIP6Config *config, const NMPlatformIP6Route *route); void nm_ip6_config_del_route (NMIP6Config *config, guint i); -guint32 nm_ip6_config_get_num_routes (const NMIP6Config *config); -const NMPlatformIP6Route *nm_ip6_config_get_route (const NMIP6Config *config, guint32 i); +guint nm_ip6_config_get_num_routes (const NMIP6Config *config); +const NMPlatformIP6Route *nm_ip6_config_get_route (const NMIP6Config *config, guint i); const NMPlatformIP6Route *nm_ip6_config_get_direct_route_for_host (const NMIP6Config *config, const struct in6_addr *host); const NMPlatformIP6Address *nm_ip6_config_get_subnet_for_host (const NMIP6Config *config, const struct in6_addr *host); -/* Nameservers */ void nm_ip6_config_reset_nameservers (NMIP6Config *config); void nm_ip6_config_add_nameserver (NMIP6Config *config, const struct in6_addr *nameserver); void nm_ip6_config_del_nameserver (NMIP6Config *config, guint i); -guint32 nm_ip6_config_get_num_nameservers (const NMIP6Config *config); +guint nm_ip6_config_get_num_nameservers (const NMIP6Config *config); const struct in6_addr *nm_ip6_config_get_nameserver (const NMIP6Config *config, guint i); -/* Domains */ void nm_ip6_config_reset_domains (NMIP6Config *config); void nm_ip6_config_add_domain (NMIP6Config *config, const char *domain); void nm_ip6_config_del_domain (NMIP6Config *config, guint i); -guint32 nm_ip6_config_get_num_domains (const NMIP6Config *config); +guint nm_ip6_config_get_num_domains (const NMIP6Config *config); const char * nm_ip6_config_get_domain (const NMIP6Config *config, guint i); -/* Search lists */ void nm_ip6_config_reset_searches (NMIP6Config *config); void nm_ip6_config_add_search (NMIP6Config *config, const char *search); void nm_ip6_config_del_search (NMIP6Config *config, guint i); -guint32 nm_ip6_config_get_num_searches (const NMIP6Config *config); +guint nm_ip6_config_get_num_searches (const NMIP6Config *config); const char * nm_ip6_config_get_search (const NMIP6Config *config, guint i); -/* DNS options */ void nm_ip6_config_reset_dns_options (NMIP6Config *config); void nm_ip6_config_add_dns_option (NMIP6Config *config, const char *option); void nm_ip6_config_del_dns_option (NMIP6Config *config, guint i); -guint32 nm_ip6_config_get_num_dns_options (const NMIP6Config *config); +guint nm_ip6_config_get_num_dns_options (const NMIP6Config *config); const char * nm_ip6_config_get_dns_option (const NMIP6Config *config, guint i); -/* DNS priority */ void nm_ip6_config_set_dns_priority (NMIP6Config *config, gint priority); gint nm_ip6_config_get_dns_priority (const NMIP6Config *config); -/* MSS */ void nm_ip6_config_set_mss (NMIP6Config *config, guint32 mss); guint32 nm_ip6_config_get_mss (const NMIP6Config *config); void nm_ip6_config_hash (const NMIP6Config *config, GChecksum *sum, gboolean dns_only); gboolean nm_ip6_config_equal (const NMIP6Config *a, const NMIP6Config *b); -/******************************************************/ +void nm_ip6_config_set_privacy (NMIP6Config *config, NMSettingIP6ConfigPrivacy privacy); + /* Testing-only functions */ gboolean nm_ip6_config_capture_resolv_conf (GArray *nameservers, diff --git a/src/tests/test-ip6-config.c b/src/tests/test-ip6-config.c index 3eceec0cbe..de890141d1 100644 --- a/src/tests/test-ip6-config.c +++ b/src/tests/test-ip6-config.c @@ -238,10 +238,13 @@ test_nm_ip6_config_addresses_sort_check (NMIP6Config *config, NMSettingIP6Config { int addr_count = nm_ip6_config_get_num_addresses (config); int i, irepeat; - NMIP6Config *copy = nmtst_ip6_config_clone (config); - NMIP6Config *copy2 = nmtst_ip6_config_clone (config); + NMIP6Config *copy, *copy2; int *idx = g_new (int, addr_count); + nm_ip6_config_set_privacy (config, use_tempaddr); + copy = nmtst_ip6_config_clone (config); + copy2 = nmtst_ip6_config_clone (config); + /* initialize the array of indeces, and keep shuffling them for every @repeat iteration. */ for (i = 0; i < addr_count; i++) idx[i] = i; @@ -257,7 +260,7 @@ test_nm_ip6_config_addresses_sort_check (NMIP6Config *config, NMSettingIP6Config } /* reorder them again */ - nm_ip6_config_addresses_sort (copy, use_tempaddr); + nm_ip6_config_addresses_sort (copy); /* check equality using nm_ip6_config_equal() */ if (!nm_ip6_config_equal (copy, config)) {