Blob Blame History Raw
From 93806baf641da6afcdfe2042c4621740352e28a2 Mon Sep 17 00:00:00 2001
From: Thomas Haller <thaller@redhat.com>
Date: Fri, 14 Oct 2016 06:08:41 +0200
Subject: [PATCH 01/10] ip-config: cleanup integer types for
 nm_ip4_config_get_num_*()

(cherry picked from commit 510626bf74c521de3dc76b9502a137f40e6bbb4f)
(cherry picked from commit 8bcf1a6e3d343f10280848f130692913f04ff195)
---
 src/nm-ip4-config.c | 32 ++++++++++++++++----------------
 src/nm-ip4-config.h | 34 +++++++++++-----------------------
 src/nm-ip6-config.c | 24 ++++++++++++------------
 src/nm-ip6-config.h | 26 +++++++++-----------------
 4 files changed, 48 insertions(+), 68 deletions(-)

diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c
index a4d4361..816c606 100644
--- a/src/nm-ip4-config.c
+++ b/src/nm-ip4-config.c
@@ -347,7 +347,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 +358,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 +1366,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++) {
@@ -1725,7 +1725,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 +1782,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 +1854,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 +1911,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 +1999,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 +2072,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 +2147,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);
@@ -2294,8 +2294,8 @@ get_property (GObject *object, guint prop_id,
 	case PROP_ADDRESS_DATA:
 		{
 			GVariantBuilder array_builder, addr_builder;
-			int naddr = nm_ip4_config_get_num_addresses (config);
-			int i;
+			guint naddr = nm_ip4_config_get_num_addresses (config);
+			guint i;
 
 			g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("aa{sv}"));
 			for (i = 0; i < naddr; i++) {
@@ -2329,8 +2329,8 @@ get_property (GObject *object, guint prop_id,
 	case PROP_ADDRESSES:
 		{
 			GVariantBuilder array_builder;
-			int naddr = nm_ip4_config_get_num_addresses (config);
-			int i;
+			guint naddr = nm_ip4_config_get_num_addresses (config);
+			guint i;
 
 			g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("aau"));
 			for (i = 0; i < naddr; i++) {
@@ -2353,7 +2353,7 @@ get_property (GObject *object, guint prop_id,
 		{
 			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 f302630..71920c9 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,7 +81,6 @@ 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);
@@ -90,73 +89,62 @@ const NMPlatformIP4Address *nm_ip4_config_get_address (const NMIP4Config *config
 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 8002d61..2030907 100644
--- a/src/nm-ip6-config.c
+++ b/src/nm-ip6-config.c
@@ -384,7 +384,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 +394,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 +712,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);
@@ -1626,7 +1626,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 +1683,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 +1755,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 +1812,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);
@@ -2038,8 +2038,8 @@ get_property (GObject *object, guint prop_id,
 	case PROP_ADDRESS_DATA:
 		{
 			GVariantBuilder array_builder, addr_builder;
-			int naddr = nm_ip6_config_get_num_addresses (config);
-			int i;
+			guint naddr = nm_ip6_config_get_num_addresses (config);
+			guint i;
 
 			g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("aa{sv}"));
 			for (i = 0; i < naddr; i++) {
@@ -2069,8 +2069,8 @@ get_property (GObject *object, guint prop_id,
 		{
 			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;
+			guint naddr = nm_ip6_config_get_num_addresses (config);
+			guint i;
 
 			g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("a(ayuay)"));
 			for (i = 0; i < naddr; i++) {
diff --git a/src/nm-ip6-config.h b/src/nm-ip6-config.h
index c3f8d9f..184d3e3 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);
@@ -93,49 +92,42 @@ gboolean nm_ip6_config_addresses_sort (NMIP6Config *config, NMSettingIP6ConfigPr
 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);
 
-- 
2.7.4

From 6a079d44e4e1179a2288f85e806565e704756e2e Mon Sep 17 00:00:00 2001
From: Beniamino Galvani <bgalvani@redhat.com>
Date: Fri, 18 Nov 2016 11:48:12 +0100
Subject: [PATCH 02/10] ip4-config: don't change order of addresses in the same
 subnet

When multiple address are assigned to an interface and the kernel must
decide which one should be used to communicate with a given IP, it
chooses the most specific one in the same subnet as the
destination. In case there are multiple addresses in the same subnet,
the primary address is choosen, which is basically the first one that
was added.

With commit 719742513705 ("device: expose NMIP4Config:addresses in
stable/defined sort order") we sorted all the addresses before
committing the configuration, with the side effect that the order no
longer respected the one in the user configuration.

Instead, change the sort function to keep the subnet order unchanged.

(cherry picked from commit e02752c2ed6a8dde884021817a5da8fc101330db)
(cherry picked from commit 56cebecd414fac495617852a995a170613d98313)
---
 src/nm-ip4-config.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c
index 816c606..6941285 100644
--- a/src/nm-ip4-config.c
+++ b/src/nm-ip4-config.c
@@ -207,8 +207,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,9 +225,15 @@ _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);
+
+	return memcmp (&n1, &n2, sizeof (guint32));
 }
 
 gboolean
-- 
2.7.4

From 45791b1c25a482a47a1b9c7cab5bc0f2c65f3ca7 Mon Sep 17 00:00:00 2001
From: Beniamino Galvani <bgalvani@redhat.com>
Date: Fri, 18 Nov 2016 11:52:38 +0100
Subject: [PATCH 03/10] ip4-config: cache addresses variants

(cherry picked from commit 5ce81e23b7508c79b036ddbf4dc3dfdd2e6faec4)
(cherry picked from commit 996f325f67da91a70f7767e248b6bcf508e63a23)
---
 src/nm-ip4-config.c | 55 +++++++++++++++++++++++++++++++++++------------------
 1 file changed, 37 insertions(+), 18 deletions(-)

diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c
index 6941285..315dddb 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 {
@@ -268,6 +270,17 @@ nm_ip4_config_addresses_sort (NMIP4Config *self)
 
 /*****************************************************************************/
 
+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)
 {
@@ -1480,8 +1493,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);
 	}
 }
 
@@ -1538,8 +1550,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
@@ -1550,8 +1561,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
@@ -2274,6 +2285,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);
@@ -2299,11 +2312,19 @@ 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;
-			guint naddr = nm_ip4_config_get_num_addresses (config);
-			guint i;
+			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);
+
+			/* 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);
@@ -2329,16 +2350,9 @@ 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;
-			guint naddr = nm_ip4_config_get_num_addresses (config);
-			guint 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);
@@ -2352,8 +2366,13 @@ 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:
-- 
2.7.4

From 1734568705e03430836f20529c9264a2dd9f9055 Mon Sep 17 00:00:00 2001
From: Beniamino Galvani <bgalvani@redhat.com>
Date: Fri, 18 Nov 2016 11:52:45 +0100
Subject: [PATCH 04/10] ip4-config: sort addresses only when reading the
 property value

Don't change the address order from configuration, but instead sort
addresses just before returning them to clients.

(cherry picked from commit 9609d4da1db564ffa2379790d26b74fd7f99fc27)
(cherry picked from commit 6fdea664a467b9cf912ac8c724b9a0086c76ce6d)
---
 src/devices/nm-device.c |  2 --
 src/nm-ip4-config.c     | 38 ++++++--------------------------------
 src/nm-ip4-config.h     |  1 -
 3 files changed, 6 insertions(+), 35 deletions(-)

diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 380e663..0904420 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)
diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c
index 315dddb..7b42235 100644
--- a/src/nm-ip4-config.c
+++ b/src/nm-ip4-config.c
@@ -238,36 +238,6 @@ _addresses_sort_cmp (gconstpointer a, gconstpointer b)
 	return memcmp (&n1, &n2, sizeof (guint32));
 }
 
-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;
-}
-
 /*****************************************************************************/
 
 static void
@@ -2315,6 +2285,7 @@ get_property (GObject *object, guint prop_id,
 	case PROP_ADDRESSES:
 		{
 			GVariantBuilder array_builder, addr_builder;
+			gs_unref_array GArray *new = NULL;
 			guint naddr, i;
 
 			g_return_if_fail (!!priv->address_data_variant == !!priv->addresses_variant);
@@ -2323,11 +2294,14 @@ get_property (GObject *object, guint prop_id,
 				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}",
@@ -2355,7 +2329,7 @@ get_property (GObject *object, guint prop_id,
 			/* 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;
diff --git a/src/nm-ip4-config.h b/src/nm-ip4-config.h
index 71920c9..6fc45dc 100644
--- a/src/nm-ip4-config.h
+++ b/src/nm-ip4-config.h
@@ -87,7 +87,6 @@ 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);
 
 void nm_ip4_config_reset_routes (NMIP4Config *config);
 void nm_ip4_config_add_route (NMIP4Config *config, const NMPlatformIP4Route *route);
-- 
2.7.4

From cfe4639961a0e19ae5aa4457566199680dfca8e4 Mon Sep 17 00:00:00 2001
From: Beniamino Galvani <bgalvani@redhat.com>
Date: Fri, 18 Nov 2016 11:52:50 +0100
Subject: [PATCH 05/10] ip6-config: cache addresses variants

(cherry picked from commit ed4d5889c7d5d2dc18353adc3a1dfeaa538c8f2e)
(cherry picked from commit 6633eaf75c1d8f1e1f42717ba9d4e95530569653)
---
 src/nm-ip6-config.c | 59 ++++++++++++++++++++++++++++++++++-------------------
 1 file changed, 38 insertions(+), 21 deletions(-)

diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c
index 2030907..b80c958 100644
--- a/src/nm-ip6-config.c
+++ b/src/nm-ip6-config.c
@@ -48,6 +48,8 @@ typedef struct {
 	int ifindex;
 	gint64 route_metric;
 	gint dns_priority;
+	GVariant *address_data_variant;
+	GVariant *addresses_variant;
 } NMIP6ConfigPrivate;
 
 struct _NMIP6Config {
@@ -106,6 +108,17 @@ nm_ip6_config_get_ifindex (const NMIP6Config *config)
 
 /******************************************************************/
 
+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():
  * @nameservers: array of struct in6_addr
@@ -287,8 +300,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);
+			notify_addresses (self);
 			return TRUE;
 		}
 	}
@@ -1282,8 +1294,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 +1351,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 +1362,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
@@ -2000,6 +2010,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,10 +2048,19 @@ 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;
-			guint naddr = nm_ip6_config_get_num_addresses (config);
-			guint i;
+			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);
 
 			g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("aa{sv}"));
 			for (i = 0; i < naddr; i++) {
@@ -2061,16 +2082,7 @@ 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);
-			guint naddr = nm_ip6_config_get_num_addresses (config);
-			guint 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++) {
@@ -2085,7 +2097,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:
-- 
2.7.4

From 4109620858ea6156a952353a4a6a7ff361d30c7a Mon Sep 17 00:00:00 2001
From: Beniamino Galvani <bgalvani@redhat.com>
Date: Fri, 18 Nov 2016 11:52:53 +0100
Subject: [PATCH 06/10] ip6-config: add nm_ip6_config_set_privacy()

(cherry picked from commit 803a79f778ddc50d9ec387ab6a01cc5f5418e20f)
(cherry picked from commit 450572cff48f0dde662cccd8d816472629ef824e)
---
 src/devices/nm-device.c     |  9 +++++----
 src/nm-ip6-config.c         | 21 ++++++++++++++++++---
 src/nm-ip6-config.h         |  5 +++--
 src/tests/test-ip6-config.c |  9 ++++++---
 4 files changed, 32 insertions(+), 12 deletions(-)

diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 0904420..cf506a4 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -5432,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,
@@ -5565,8 +5567,7 @@ 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);
+	nm_ip6_config_addresses_sort (composite);
 
 	/* Allow setting MTU etc */
 	if (commit) {
diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c
index b80c958..893302b 100644
--- a/src/nm-ip6-config.c
+++ b/src/nm-ip6-config.c
@@ -50,6 +50,7 @@ typedef struct {
 	gint dns_priority;
 	GVariant *address_data_variant;
 	GVariant *addresses_variant;
+	NMSettingIP6ConfigPrivacy privacy;
 } NMIP6ConfigPrivate;
 
 struct _NMIP6Config {
@@ -106,7 +107,15 @@ 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)
@@ -279,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;
@@ -294,7 +303,8 @@ 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);
@@ -1168,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. */
diff --git a/src/nm-ip6-config.h b/src/nm-ip6-config.h
index 184d3e3..9454c0f 100644
--- a/src/nm-ip6-config.h
+++ b/src/nm-ip6-config.h
@@ -88,7 +88,7 @@ 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);
 
@@ -134,7 +134,8 @@ 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 3eceec0..de89014 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)) {
-- 
2.7.4

From 9edf0387766c4060b3e8472eb1eb44e66fd968de Mon Sep 17 00:00:00 2001
From: Beniamino Galvani <bgalvani@redhat.com>
Date: Fri, 18 Nov 2016 11:52:56 +0100
Subject: [PATCH 07/10] ip6-config: sort addresses only when reading the
 property value

Don't change the address order from configuration, but instead sort
addresses just before returning them to clients.

(cherry picked from commit 0a0bca9c7fad072c31c91f93a9200c83aab37d0c)
(cherry picked from commit 2ea42eee5ab11f8540dfec4140e548b9ee48af69)
---
 src/devices/nm-device.c | 2 --
 src/nm-ip6-config.c     | 9 +++++++--
 2 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index cf506a4..262ef86 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -5567,8 +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);
-
 	/* Allow setting MTU etc */
 	if (commit) {
 		NMUtilsIPv6IfaceId iid;
diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c
index 893302b..a021124 100644
--- a/src/nm-ip6-config.c
+++ b/src/nm-ip6-config.c
@@ -2066,6 +2066,7 @@ get_property (GObject *object, guint prop_id,
 	case PROP_ADDRESSES:
 		{
 			GVariantBuilder array_builder, addr_builder;
+			gs_unref_array GArray *new = NULL;
 			const struct in6_addr *gateway;
 			guint naddr, i;
 
@@ -2076,10 +2077,14 @@ get_property (GObject *object, guint prop_id,
 
 			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}",
@@ -2101,7 +2106,7 @@ get_property (GObject *object, guint prop_id,
 
 			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,
-- 
2.7.4

From acddbf6f801303698a0903c835472691ecd1a837 Mon Sep 17 00:00:00 2001
From: Beniamino Galvani <bgalvani@redhat.com>
Date: Mon, 9 Jan 2017 17:57:45 +0100
Subject: [PATCH 08/10] platform: don't update IPv6 temporary addresses

The kernel already takes care of adding and updating temporary
addresses when an address with IFA_F_MANAGETEMPADDR flag is added or
updated; doing it also in nm_platform_ip6_address_sync() can overwrite
the changes done by kernel, especially because since commit
0a0bca9c7fad ("ip6-config: sort addresses only when reading the
property value") there is no guarantee that temporary addresses are
before the public ones in the IPv6 configuration.

Still delete temporary addresses, but don't add or update them.

(cherry picked from commit 1dbd9d7948e61f44a56e256c4d9fe60831663861)
(cherry picked from commit a25b3327c7ffdf528da7e47a819201e216d17829)
---
 src/platform/nm-platform.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
index 9dace69..2d69712 100644
--- a/src/platform/nm-platform.c
+++ b/src/platform/nm-platform.c
@@ -2816,6 +2816,11 @@ nm_platform_ip6_address_sync (NMPlatform *self, int ifindex, const GArray *known
 		const NMPlatformIP6Address *known_address = &g_array_index (known_addresses, NMPlatformIP6Address, i);
 		guint32 lifetime, preferred;
 
+		if (NM_FLAGS_HAS (known_address->n_ifa_flags, IFA_F_TEMPORARY)) {
+			/* Kernel manages these */
+			continue;
+		}
+
 		if (!nm_utils_lifetime_get (known_address->timestamp, known_address->lifetime, known_address->preferred,
 		                            now, &lifetime, &preferred))
 			continue;
-- 
2.7.4

From 47c0c4cb696dd378e4273d0ff19c8b4ef8b5cbf2 Mon Sep 17 00:00:00 2001
From: Beniamino Galvani <bgalvani@redhat.com>
Date: Mon, 14 Nov 2016 20:52:24 +0100
Subject: [PATCH 09/10] platform: fix the order of addition of primary and
 secondary IPv4 addresses

nm_platform_ip4_address_sync() tries to apply the new configuration
with the minimum effort and doesn't delete addresses if they are
already present on the interface. This can break the ordering, as an
existing address would be promoted by kernel to primary, even if it
was last in our configuration.

Add some logic to ensure the correct order of addresses is always
enforced. This fixes situations like:

 # nmcli connection add type ethernet ifname eth0 con-name t \
                        ipv4.method manual \
                        ipv4.addresses "1.1.1.1/24,1.1.1.2/24,1.1.1.5/24"
 # nmcli connection up t

  => addresses are applied in the right order:
     inet 1.1.1.1/24 brd 1.1.1.255 scope global eth0
     inet 1.1.1.2/24 brd 1.1.1.255 scope global secondary eth0
     inet 1.1.1.5/24 brd 1.1.1.255 scope global secondary eth0

 # nmcli connection mod t ipv4.addresses "1.1.1.5/24,1.1.1.2/24,1.1.1.1/24"
 # nmcli device reapply eth0

  => order is wrong:
     inet 1.1.1.2/24 brd 1.1.1.255 scope global eth0
     inet 1.1.1.5/24 brd 1.1.1.255 scope global secondary eth0
     inet 1.1.1.1/24 brd 1.1.1.255 scope global secondary eth0

Co-Authored-By: Thomas Haller <thaller@redhat.com>
(cherry picked from commit 2f68a5004153cea9878999bf3a442ecda263e5f7)
(cherry picked from commit 8b36e99ffea19416011ef8a60be8e7acf9f69467)
---
 src/platform/nm-platform.c | 161 ++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 151 insertions(+), 10 deletions(-)

diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
index 2d69712..9c8af28 100644
--- a/src/platform/nm-platform.c
+++ b/src/platform/nm-platform.c
@@ -2663,14 +2663,14 @@ nm_platform_ip6_address_get (NMPlatform *self, int ifindex, struct in6_addr addr
 	return klass->ip6_address_get (self, ifindex, address, plen);
 }
 
-static gboolean
+static const NMPlatformIP4Address *
 array_contains_ip4_address (const GArray *addresses, const NMPlatformIP4Address *address, gint32 now)
 {
 	guint len = addresses ? addresses->len : 0;
 	guint i;
 
 	for (i = 0; i < len; i++) {
-		NMPlatformIP4Address *candidate = &g_array_index (addresses, NMPlatformIP4Address, i);
+		const NMPlatformIP4Address *candidate = &g_array_index (addresses, NMPlatformIP4Address, i);
 
 		if (   candidate->address == address->address
 		    && candidate->plen == address->plen
@@ -2679,11 +2679,11 @@ array_contains_ip4_address (const GArray *addresses, const NMPlatformIP4Address
 
 			if (nm_utils_lifetime_get (candidate->timestamp, candidate->lifetime, candidate->preferred,
 			                           now, &lifetime, &preferred))
-				return TRUE;
+				return candidate;
 		}
 	}
 
-	return FALSE;
+	return NULL;
 }
 
 static gboolean
@@ -2707,6 +2707,97 @@ array_contains_ip6_address (const GArray *addresses, const NMPlatformIP6Address
 	return FALSE;
 }
 
+static gboolean
+_ptr_inside_ip4_addr_array (const GArray *array, gconstpointer needle)
+{
+	return    needle >= (gconstpointer) &g_array_index (array, const NMPlatformIP4Address, 0)
+	       && needle <  (gconstpointer) &g_array_index (array, const NMPlatformIP4Address, array->len);
+}
+
+static void
+ip4_addr_subnets_destroy_index (GHashTable *ht, const GArray *addresses)
+{
+	GHashTableIter iter;
+	gpointer p;
+
+	g_hash_table_iter_init (&iter, ht);
+
+	while (g_hash_table_iter_next (&iter, NULL, &p)) {
+		if (!_ptr_inside_ip4_addr_array (addresses, p)) {
+			g_ptr_array_free ((GPtrArray *) p, TRUE);
+		}
+	}
+
+	g_hash_table_unref (ht);
+}
+
+static GHashTable *
+ip4_addr_subnets_build_index (const GArray *addresses, gboolean consider_flags)
+{
+	const NMPlatformIP4Address *address;
+	gpointer p;
+	GHashTable *subnets;
+	GPtrArray *ptr;
+	guint32 net;
+	guint i;
+	gint position;
+
+	if (!addresses)
+		return NULL;
+
+	subnets = g_hash_table_new_full (g_direct_hash,
+	                                 g_direct_equal,
+	                                 NULL,
+	                                 NULL);
+
+	/* Build a hash table of all addresses per subnet */
+	for (i = 0; i < addresses->len; i++) {
+		address = &g_array_index (addresses, const NMPlatformIP4Address, i);
+		net = address->address & nm_utils_ip4_prefix_to_netmask (address->plen);
+		if (!g_hash_table_lookup_extended (subnets, GUINT_TO_POINTER (net), NULL, &p)) {
+			g_hash_table_insert (subnets, GUINT_TO_POINTER (net), (gpointer) address);
+			continue;
+		}
+		if (_ptr_inside_ip4_addr_array (addresses, p)) {
+			ptr = g_ptr_array_new ();
+			g_hash_table_insert (subnets, GUINT_TO_POINTER (net), ptr);
+			g_ptr_array_add (ptr, p);
+		} else
+			ptr = p;
+
+		if (!consider_flags || NM_FLAGS_HAS (address->n_ifa_flags, IFA_F_SECONDARY))
+			position = -1; /* append */
+		else
+			position = 0; /* prepend */
+
+		g_ptr_array_insert (ptr, position, (gpointer) address);
+	}
+
+	return subnets;
+}
+
+static gboolean
+ip4_addr_subnets_is_secondary (const NMPlatformIP4Address *address, GHashTable *subnets, const GArray *addresses, GPtrArray **out_addr_list)
+{
+	GPtrArray *addr_list;
+	gpointer p;
+	guint32 net;
+
+	net = address->address & nm_utils_ip4_prefix_to_netmask (address->plen);
+	p = g_hash_table_lookup (subnets, GUINT_TO_POINTER (net));
+	nm_assert (p);
+	if (!_ptr_inside_ip4_addr_array (addresses, p)) {
+		addr_list = p;
+		if (addr_list->pdata[0] != address) {
+			NM_SET_OUT (out_addr_list, addr_list);
+			return TRUE;
+		}
+	} else
+		nm_assert ((gconstpointer) address == p);
+	NM_SET_OUT (out_addr_list, NULL);
+	return FALSE;
+}
+
 /**
  * nm_platform_ip4_address_sync:
  * @self: platform instance
@@ -2728,19 +2819,64 @@ nm_platform_ip4_address_sync (NMPlatform *self, int ifindex, const GArray *known
 {
 	GArray *addresses;
 	NMPlatformIP4Address *address;
+	const NMPlatformIP4Address *known_address;
 	gint32 now = nm_utils_get_monotonic_timestamp_s ();
-	int i;
+	GHashTable *plat_subnets;
+	GHashTable *known_subnets;
+	GPtrArray *ptr;
+	int i, j;
 
 	_CHECK_SELF (self, klass, FALSE);
 
-	/* Delete unknown addresses */
 	addresses = nm_platform_ip4_address_get_all (self, ifindex);
+	plat_subnets = ip4_addr_subnets_build_index (addresses, TRUE);
+	known_subnets = ip4_addr_subnets_build_index (known_addresses, FALSE);
+
+	/* Delete unknown addresses */
 	for (i = 0; i < addresses->len; i++) {
 		address = &g_array_index (addresses, NMPlatformIP4Address, i);
 
-		if (!array_contains_ip4_address (known_addresses, address, now))
-			nm_platform_ip4_address_delete (self, ifindex, address->address, address->plen, address->peer_address);
+		if (!address->ifindex) {
+			/* Already deleted */
+			continue;
+		}
+
+		known_address = array_contains_ip4_address (known_addresses, address, now);
+		if (known_address) {
+			gboolean secondary;
+
+			secondary = ip4_addr_subnets_is_secondary (known_address, known_subnets, known_addresses, NULL);
+			/* Ignore the matching address if it has a different primary/slave
+			 * role. */
+			if (secondary != NM_FLAGS_HAS (address->n_ifa_flags, IFA_F_SECONDARY))
+				known_address = NULL;
+		}
+
+		if (!known_address) {
+			nm_platform_ip4_address_delete (self, ifindex,
+			                                address->address,
+			                                address->plen,
+			                                address->peer_address);
+			if (   !ip4_addr_subnets_is_secondary (address, plat_subnets, addresses, &ptr)
+			    && ptr) {
+				/* If we just deleted a primary addresses and there were
+				 * secondary ones the kernel can do two things, depending on
+				 * version and sysctl setting: delete also secondary addresses
+				 * or promote a secondary to primary. Ensure that secondary
+				 * addresses are deleted, so that we can start with a clean
+				 * slate and add addresses in the right order. */
+				for (j = 1; j < ptr->len; j++) {
+					address = ptr->pdata[j];
+					nm_platform_ip4_address_delete (self, ifindex,
+					                                address->address,
+					                                address->plen,
+					                                address->peer_address);
+					address->ifindex = 0;
+				}
+			}
+		}
 	}
+	ip4_addr_subnets_destroy_index (plat_subnets, addresses);
 	g_array_free (addresses, TRUE);
 
 	if (out_added_addresses)
@@ -2751,17 +2887,20 @@ nm_platform_ip4_address_sync (NMPlatform *self, int ifindex, const GArray *known
 
 	/* Add missing addresses */
 	for (i = 0; i < known_addresses->len; i++) {
-		const NMPlatformIP4Address *known_address = &g_array_index (known_addresses, NMPlatformIP4Address, i);
 		guint32 lifetime, preferred;
 
+		known_address = &g_array_index (known_addresses, NMPlatformIP4Address, i);
+
 		if (!nm_utils_lifetime_get (known_address->timestamp, known_address->lifetime, known_address->preferred,
 		                            now, &lifetime, &preferred))
 			continue;
 
 		if (!nm_platform_ip4_address_add (self, ifindex, known_address->address, known_address->plen,
 		                                  known_address->peer_address, lifetime, preferred,
-		                                  0, known_address->label))
+		                                  0, known_address->label)) {
+			ip4_addr_subnets_destroy_index (known_subnets, known_addresses);
 			return FALSE;
+		}
 
 		if (out_added_addresses) {
 			if (!*out_added_addresses)
@@ -2770,6 +2909,8 @@ nm_platform_ip4_address_sync (NMPlatform *self, int ifindex, const GArray *known
 		}
 	}
 
+	ip4_addr_subnets_destroy_index (known_subnets, known_addresses);
+
 	return TRUE;
 }
 
-- 
2.7.4

From 0f74ac6831027e15ee35822c83674540c1cb82bc Mon Sep 17 00:00:00 2001
From: Beniamino Galvani <bgalvani@redhat.com>
Date: Wed, 8 Feb 2017 14:47:14 +0100
Subject: [PATCH 10/10] platform: fix detection of primary/secondary addresses

ip4_addr_subnets_is_secondary() should fill the list of addresses in
the same subnet also when returning FALSE, because
nm_platform_ip4_address_sync() uses it.

Fixes: 2f68a5004153cea9878999bf3a442ecda263e5f7
(cherry picked from commit a347962831ed127338a13b7a0939302d42bcfe60)
(cherry picked from commit 6913311d47a9045ac10f855fc3097c2304c56c43)
---
 src/platform/nm-platform.c | 22 +++++++++++++++++-----
 1 file changed, 17 insertions(+), 5 deletions(-)

diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
index 9c8af28..8fba7ab 100644
--- a/src/platform/nm-platform.c
+++ b/src/platform/nm-platform.c
@@ -2776,6 +2776,18 @@ ip4_addr_subnets_build_index (const GArray *addresses, gboolean consider_flags)
 	return subnets;
 }
 
+/**
+ * ip4_addr_subnets_is_secondary:
+ * @address: an address
+ * @subnets: the hash table mapping subnets to addresses
+ * @addresses: array of addresses in the hash table
+ * @out_addr_list: array of addresses belonging to the same subnet
+ *
+ * Checks whether @address is secondary and returns in @out_addr_list the list of addresses
+ * belonging to the same subnet, if it contains other elements.
+ *
+ * Returns: %TRUE if the address is secondary, %FALSE otherwise
+ */
 static gboolean
 ip4_addr_subnets_is_secondary (const NMPlatformIP4Address *address, GHashTable *subnets, const GArray *addresses, GPtrArray **out_addr_list)
 {
@@ -2788,13 +2800,13 @@ ip4_addr_subnets_is_secondary (const NMPlatformIP4Address *address, GHashTable *
 	nm_assert (p);
 	if (!_ptr_inside_ip4_addr_array (addresses, p)) {
 		addr_list = p;
-		if (addr_list->pdata[0] != address) {
-			NM_SET_OUT (out_addr_list, addr_list);
+		NM_SET_OUT (out_addr_list, addr_list);
+		if (addr_list->pdata[0] != address)
 			return TRUE;
-		}
-	} else
+	} else {
 		nm_assert ((gconstpointer) address == p);
-	NM_SET_OUT (out_addr_list, NULL);
+		NM_SET_OUT (out_addr_list, NULL);
+	}
 	return FALSE;
 }
 
-- 
2.7.4