summary refs log tree commit diff
path: root/src/nm-ip4-config.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nm-ip4-config.c')
-rw-r--r--src/nm-ip4-config.c5260
1 files changed, 2491 insertions, 2769 deletions
diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c
index 23c0d3f9..ea08450d 100644
--- a/src/nm-ip4-config.c
+++ b/src/nm-ip4-config.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0+
+/* SPDX-License-Identifier: GPL-2.0+ */
 /*
  * Copyright (C) 2005 - 2017 Red Hat, Inc.
  * Copyright (C) 2006 - 2008 Novell, Inc.
@@ -25,181 +25,183 @@
 /*****************************************************************************/
 
 /* internal guint32 are assigned to gobject properties of type uint. Ensure, that uint is large enough */
-G_STATIC_ASSERT (sizeof (uint) >= sizeof (guint32));
-G_STATIC_ASSERT (G_MAXUINT >= 0xFFFFFFFF);
+G_STATIC_ASSERT(sizeof(uint) >= sizeof(guint32));
+G_STATIC_ASSERT(G_MAXUINT >= 0xFFFFFFFF);
 
 /*****************************************************************************/
 
 static gboolean
-_route_valid (const NMPlatformIP4Route *r)
+_route_valid(const NMPlatformIP4Route *r)
 {
-	return    r
-	       && r->plen <= 32
-	       && r->network == nm_utils_ip4_address_clear_host_address (r->network, r->plen);
+    return r && r->plen <= 32
+           && r->network == nm_utils_ip4_address_clear_host_address(r->network, r->plen);
 }
 
 /*****************************************************************************/
 
 static void
-_idx_obj_id_hash_update (const NMDedupMultiIdxType *idx_type,
-                         const NMDedupMultiObj *obj,
-                         NMHashState *h)
+_idx_obj_id_hash_update(const NMDedupMultiIdxType *idx_type,
+                        const NMDedupMultiObj *    obj,
+                        NMHashState *              h)
 {
-	nmp_object_id_hash_update ((NMPObject *) obj, h);
+    nmp_object_id_hash_update((NMPObject *) obj, h);
 }
 
 static gboolean
-_idx_obj_id_equal (const NMDedupMultiIdxType *idx_type,
-                   const NMDedupMultiObj *obj_a,
-                   const NMDedupMultiObj *obj_b)
+_idx_obj_id_equal(const NMDedupMultiIdxType *idx_type,
+                  const NMDedupMultiObj *    obj_a,
+                  const NMDedupMultiObj *    obj_b)
 {
-	return nmp_object_id_equal ((NMPObject *) obj_a, (NMPObject *) obj_b);
+    return nmp_object_id_equal((NMPObject *) obj_a, (NMPObject *) obj_b);
 }
 
 void
-nm_ip_config_dedup_multi_idx_type_init (NMIPConfigDedupMultiIdxType *idx_type,
-                                        NMPObjectType obj_type)
+nm_ip_config_dedup_multi_idx_type_init(NMIPConfigDedupMultiIdxType *idx_type,
+                                       NMPObjectType                obj_type)
 {
-	static const NMDedupMultiIdxTypeClass idx_type_class = {
-		.idx_obj_id_hash_update = _idx_obj_id_hash_update,
-		.idx_obj_id_equal = _idx_obj_id_equal,
-	};
+    static const NMDedupMultiIdxTypeClass idx_type_class = {
+        .idx_obj_id_hash_update = _idx_obj_id_hash_update,
+        .idx_obj_id_equal       = _idx_obj_id_equal,
+    };
 
-	nm_dedup_multi_idx_type_init ((NMDedupMultiIdxType *) idx_type,
-	                              &idx_type_class);
-	idx_type->obj_type = obj_type;
+    nm_dedup_multi_idx_type_init((NMDedupMultiIdxType *) idx_type, &idx_type_class);
+    idx_type->obj_type = obj_type;
 }
 
 /*****************************************************************************/
 
 gboolean
-_nm_ip_config_add_obj (NMDedupMultiIndex *multi_idx,
-                       NMIPConfigDedupMultiIdxType *idx_type,
-                       int ifindex,
-                       const NMPObject *obj_new,
-                       const NMPlatformObject *pl_new,
-                       gboolean merge,
-                       gboolean append_force,
-                       const NMPObject **out_obj_old /* returns a reference! */,
-                       const NMPObject **out_obj_new /* does not return a reference */)
-{
-	NMPObject obj_new_stackinit;
-	const NMDedupMultiEntry *entry_old;
-	const NMDedupMultiEntry *entry_new;
-
-	nm_assert (multi_idx);
-	nm_assert (idx_type);
-	nm_assert (NM_IN_SET (idx_type->obj_type, NMP_OBJECT_TYPE_IP4_ADDRESS,
-	                                          NMP_OBJECT_TYPE_IP4_ROUTE,
-	                                          NMP_OBJECT_TYPE_IP6_ADDRESS,
-	                                          NMP_OBJECT_TYPE_IP6_ROUTE));
-	nm_assert (ifindex > 0);
-
-	/* we go through extra lengths to accept a full obj_new object. That one,
-	 * can be reused by increasing the ref-count. */
-	if (!obj_new) {
-		nm_assert (pl_new);
-		obj_new = nmp_object_stackinit (&obj_new_stackinit, idx_type->obj_type, pl_new);
-		NMP_OBJECT_CAST_OBJ_WITH_IFINDEX (&obj_new_stackinit)->ifindex = ifindex;
-	} else {
-		nm_assert (!pl_new);
-		nm_assert (NMP_OBJECT_GET_TYPE (obj_new) == idx_type->obj_type);
-		if (NMP_OBJECT_CAST_OBJ_WITH_IFINDEX (obj_new)->ifindex != ifindex) {
-			obj_new = nmp_object_stackinit_obj (&obj_new_stackinit, obj_new);
-			NMP_OBJECT_CAST_OBJ_WITH_IFINDEX (&obj_new_stackinit)->ifindex = ifindex;
-		}
-	}
-	nm_assert (NMP_OBJECT_GET_TYPE (obj_new) == idx_type->obj_type);
-	nm_assert (nmp_object_is_alive (obj_new));
-
-	entry_old = nm_dedup_multi_index_lookup_obj (multi_idx, &idx_type->parent, obj_new);
-
-	if (entry_old) {
-		gboolean modified = FALSE;
-		const NMPObject *obj_old = entry_old->obj;
-
-		if (nmp_object_equal (obj_new, obj_old)) {
-			nm_dedup_multi_entry_set_dirty (entry_old, FALSE);
-			goto append_force_and_out;
-		}
-
-		/* if @merge, we merge the new object with the existing one.
-		 * Otherwise, we replace it entirely. */
-		if (merge) {
-			switch (idx_type->obj_type) {
-			case NMP_OBJECT_TYPE_IP4_ADDRESS:
-			case NMP_OBJECT_TYPE_IP6_ADDRESS:
-				/* for addresses that we read from the kernel, we keep the timestamps as defined
-				 * by the previous source (item_old). The reason is, that the other source configured the lifetimes
-				 * with "what should be" and the kernel values are "what turned out after configuring it".
-				 *
-				 * For other sources, the longer lifetime wins. */
-				if (   (   obj_new->ip_address.addr_source == NM_IP_CONFIG_SOURCE_KERNEL
-				        && obj_old->ip_address.addr_source != NM_IP_CONFIG_SOURCE_KERNEL)
-				    || nm_platform_ip_address_cmp_expiry (NMP_OBJECT_CAST_IP_ADDRESS (obj_old), NMP_OBJECT_CAST_IP_ADDRESS(obj_new)) > 0) {
-					obj_new = nmp_object_stackinit_obj (&obj_new_stackinit, obj_new);
-					obj_new_stackinit.ip_address.timestamp = NMP_OBJECT_CAST_IP_ADDRESS (obj_old)->timestamp;
-					obj_new_stackinit.ip_address.lifetime  = NMP_OBJECT_CAST_IP_ADDRESS (obj_old)->lifetime;
-					obj_new_stackinit.ip_address.preferred = NMP_OBJECT_CAST_IP_ADDRESS (obj_old)->preferred;
-					modified = TRUE;
-				}
-
-				/* keep the maximum addr_source. */
-				if (obj_new->ip_address.addr_source < obj_old->ip_address.addr_source) {
-					obj_new = nmp_object_stackinit_obj (&obj_new_stackinit, obj_new);
-					obj_new_stackinit.ip_address.addr_source = obj_old->ip_address.addr_source;
-					modified = TRUE;
-				}
-				break;
-			case NMP_OBJECT_TYPE_IP4_ROUTE:
-			case NMP_OBJECT_TYPE_IP6_ROUTE:
-				/* keep the maximum rt_source. */
-				if (obj_new->ip_route.rt_source < obj_old->ip_route.rt_source) {
-					obj_new = nmp_object_stackinit_obj (&obj_new_stackinit, obj_new);
-					obj_new_stackinit.ip_route.rt_source = obj_old->ip_route.rt_source;
-					modified = TRUE;
-				}
-				break;
-			default:
-				nm_assert_not_reached ();
-				break;
-			}
-
-			if (   modified
-			    && nmp_object_equal (obj_new, obj_old)) {
-				nm_dedup_multi_entry_set_dirty (entry_old, FALSE);
-				goto append_force_and_out;
-			}
-		}
-	}
-
-	if (!nm_dedup_multi_index_add_full (multi_idx,
-	                                    &idx_type->parent,
-	                                    obj_new,
-	                                      append_force
-	                                    ? NM_DEDUP_MULTI_IDX_MODE_APPEND_FORCE
-	                                    : NM_DEDUP_MULTI_IDX_MODE_APPEND,
-	                                    NULL,
-	                                    entry_old ?: NM_DEDUP_MULTI_ENTRY_MISSING,
-	                                    NULL,
-	                                    &entry_new,
-	                                    out_obj_old)) {
-		nm_assert_not_reached ();
-		NM_SET_OUT (out_obj_new, NULL);
-		return FALSE;
-	}
-
-	NM_SET_OUT (out_obj_new, entry_new->obj);
-	return TRUE;
+_nm_ip_config_add_obj(NMDedupMultiIndex *          multi_idx,
+                      NMIPConfigDedupMultiIdxType *idx_type,
+                      int                          ifindex,
+                      const NMPObject *            obj_new,
+                      const NMPlatformObject *     pl_new,
+                      gboolean                     merge,
+                      gboolean                     append_force,
+                      const NMPObject **           out_obj_old /* returns a reference! */,
+                      const NMPObject **           out_obj_new /* does not return a reference */)
+{
+    NMPObject                obj_new_stackinit;
+    const NMDedupMultiEntry *entry_old;
+    const NMDedupMultiEntry *entry_new;
+
+    nm_assert(multi_idx);
+    nm_assert(idx_type);
+    nm_assert(NM_IN_SET(idx_type->obj_type,
+                        NMP_OBJECT_TYPE_IP4_ADDRESS,
+                        NMP_OBJECT_TYPE_IP4_ROUTE,
+                        NMP_OBJECT_TYPE_IP6_ADDRESS,
+                        NMP_OBJECT_TYPE_IP6_ROUTE));
+    nm_assert(ifindex > 0);
+
+    /* we go through extra lengths to accept a full obj_new object. That one,
+     * can be reused by increasing the ref-count. */
+    if (!obj_new) {
+        nm_assert(pl_new);
+        obj_new = nmp_object_stackinit(&obj_new_stackinit, idx_type->obj_type, pl_new);
+        NMP_OBJECT_CAST_OBJ_WITH_IFINDEX(&obj_new_stackinit)->ifindex = ifindex;
+    } else {
+        nm_assert(!pl_new);
+        nm_assert(NMP_OBJECT_GET_TYPE(obj_new) == idx_type->obj_type);
+        if (NMP_OBJECT_CAST_OBJ_WITH_IFINDEX(obj_new)->ifindex != ifindex) {
+            obj_new = nmp_object_stackinit_obj(&obj_new_stackinit, obj_new);
+            NMP_OBJECT_CAST_OBJ_WITH_IFINDEX(&obj_new_stackinit)->ifindex = ifindex;
+        }
+    }
+    nm_assert(NMP_OBJECT_GET_TYPE(obj_new) == idx_type->obj_type);
+    nm_assert(nmp_object_is_alive(obj_new));
+
+    entry_old = nm_dedup_multi_index_lookup_obj(multi_idx, &idx_type->parent, obj_new);
+
+    if (entry_old) {
+        gboolean         modified = FALSE;
+        const NMPObject *obj_old  = entry_old->obj;
+
+        if (nmp_object_equal(obj_new, obj_old)) {
+            nm_dedup_multi_entry_set_dirty(entry_old, FALSE);
+            goto append_force_and_out;
+        }
+
+        /* if @merge, we merge the new object with the existing one.
+         * Otherwise, we replace it entirely. */
+        if (merge) {
+            switch (idx_type->obj_type) {
+            case NMP_OBJECT_TYPE_IP4_ADDRESS:
+            case NMP_OBJECT_TYPE_IP6_ADDRESS:
+                /* for addresses that we read from the kernel, we keep the timestamps as defined
+                 * by the previous source (item_old). The reason is, that the other source configured the lifetimes
+                 * with "what should be" and the kernel values are "what turned out after configuring it".
+                 *
+                 * For other sources, the longer lifetime wins. */
+                if ((obj_new->ip_address.addr_source == NM_IP_CONFIG_SOURCE_KERNEL
+                     && obj_old->ip_address.addr_source != NM_IP_CONFIG_SOURCE_KERNEL)
+                    || nm_platform_ip_address_cmp_expiry(NMP_OBJECT_CAST_IP_ADDRESS(obj_old),
+                                                         NMP_OBJECT_CAST_IP_ADDRESS(obj_new))
+                           > 0) {
+                    obj_new = nmp_object_stackinit_obj(&obj_new_stackinit, obj_new);
+                    obj_new_stackinit.ip_address.timestamp =
+                        NMP_OBJECT_CAST_IP_ADDRESS(obj_old)->timestamp;
+                    obj_new_stackinit.ip_address.lifetime =
+                        NMP_OBJECT_CAST_IP_ADDRESS(obj_old)->lifetime;
+                    obj_new_stackinit.ip_address.preferred =
+                        NMP_OBJECT_CAST_IP_ADDRESS(obj_old)->preferred;
+                    modified = TRUE;
+                }
+
+                /* keep the maximum addr_source. */
+                if (obj_new->ip_address.addr_source < obj_old->ip_address.addr_source) {
+                    obj_new = nmp_object_stackinit_obj(&obj_new_stackinit, obj_new);
+                    obj_new_stackinit.ip_address.addr_source = obj_old->ip_address.addr_source;
+                    modified                                 = TRUE;
+                }
+                break;
+            case NMP_OBJECT_TYPE_IP4_ROUTE:
+            case NMP_OBJECT_TYPE_IP6_ROUTE:
+                /* keep the maximum rt_source. */
+                if (obj_new->ip_route.rt_source < obj_old->ip_route.rt_source) {
+                    obj_new = nmp_object_stackinit_obj(&obj_new_stackinit, obj_new);
+                    obj_new_stackinit.ip_route.rt_source = obj_old->ip_route.rt_source;
+                    modified                             = TRUE;
+                }
+                break;
+            default:
+                nm_assert_not_reached();
+                break;
+            }
+
+            if (modified && nmp_object_equal(obj_new, obj_old)) {
+                nm_dedup_multi_entry_set_dirty(entry_old, FALSE);
+                goto append_force_and_out;
+            }
+        }
+    }
+
+    if (!nm_dedup_multi_index_add_full(multi_idx,
+                                       &idx_type->parent,
+                                       obj_new,
+                                       append_force ? NM_DEDUP_MULTI_IDX_MODE_APPEND_FORCE
+                                                    : NM_DEDUP_MULTI_IDX_MODE_APPEND,
+                                       NULL,
+                                       entry_old ?: NM_DEDUP_MULTI_ENTRY_MISSING,
+                                       NULL,
+                                       &entry_new,
+                                       out_obj_old)) {
+        nm_assert_not_reached();
+        NM_SET_OUT(out_obj_new, NULL);
+        return FALSE;
+    }
+
+    NM_SET_OUT(out_obj_new, entry_new->obj);
+    return TRUE;
 
 append_force_and_out:
-	NM_SET_OUT (out_obj_old, nmp_object_ref (entry_old->obj));
-	NM_SET_OUT (out_obj_new, entry_old->obj);
-	if (append_force) {
-		if (nm_dedup_multi_entry_reorder (entry_old, NULL, TRUE))
-			return TRUE;
-	}
-	return FALSE;
+    NM_SET_OUT(out_obj_old, nmp_object_ref(entry_old->obj));
+    NM_SET_OUT(out_obj_new, entry_old->obj);
+    if (append_force) {
+        if (nm_dedup_multi_entry_reorder(entry_old, NULL, TRUE))
+            return TRUE;
+    }
+    return FALSE;
 }
 
 /**
@@ -215,1207 +217,1014 @@ append_force_and_out:
  * Returns: the found entry or %NULL.
  */
 const NMDedupMultiEntry *
-_nm_ip_config_lookup_ip_route (const NMDedupMultiIndex *multi_idx,
-                               const NMIPConfigDedupMultiIdxType *idx_type,
-                               const NMPObject *needle,
-                               NMPlatformIPRouteCmpType cmp_type)
-{
-	const NMDedupMultiEntry *entry;
-
-	nm_assert (multi_idx);
-	nm_assert (idx_type);
-	nm_assert (NM_IN_SET (idx_type->obj_type, NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE));
-	nm_assert (NMP_OBJECT_GET_TYPE (needle) == idx_type->obj_type);
-
-	entry = nm_dedup_multi_index_lookup_obj (multi_idx,
-	                                         &idx_type->parent,
-	                                         needle);
-	if (!entry)
-		return NULL;
-
-	if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID) {
-		nm_assert (   (   NMP_OBJECT_GET_TYPE (needle) == NMP_OBJECT_TYPE_IP4_ROUTE
-		               && nm_platform_ip4_route_cmp (NMP_OBJECT_CAST_IP4_ROUTE (entry->obj), NMP_OBJECT_CAST_IP4_ROUTE (needle), cmp_type) == 0)
-		           || (   NMP_OBJECT_GET_TYPE (needle) == NMP_OBJECT_TYPE_IP6_ROUTE
-		               && nm_platform_ip6_route_cmp (NMP_OBJECT_CAST_IP6_ROUTE (entry->obj), NMP_OBJECT_CAST_IP6_ROUTE (needle), cmp_type) == 0));
-	} else {
-		if (NMP_OBJECT_GET_TYPE (needle) == NMP_OBJECT_TYPE_IP4_ROUTE) {
-			if (nm_platform_ip4_route_cmp (NMP_OBJECT_CAST_IP4_ROUTE (entry->obj),
-			                               NMP_OBJECT_CAST_IP4_ROUTE (needle),
-			                               cmp_type) != 0)
-				return NULL;
-		} else {
-			if (nm_platform_ip6_route_cmp (NMP_OBJECT_CAST_IP6_ROUTE (entry->obj),
-			                               NMP_OBJECT_CAST_IP6_ROUTE (needle),
-			                               cmp_type) != 0)
-				return NULL;
-		}
-	}
-	return entry;
+_nm_ip_config_lookup_ip_route(const NMDedupMultiIndex *          multi_idx,
+                              const NMIPConfigDedupMultiIdxType *idx_type,
+                              const NMPObject *                  needle,
+                              NMPlatformIPRouteCmpType           cmp_type)
+{
+    const NMDedupMultiEntry *entry;
+
+    nm_assert(multi_idx);
+    nm_assert(idx_type);
+    nm_assert(NM_IN_SET(idx_type->obj_type, NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE));
+    nm_assert(NMP_OBJECT_GET_TYPE(needle) == idx_type->obj_type);
+
+    entry = nm_dedup_multi_index_lookup_obj(multi_idx, &idx_type->parent, needle);
+    if (!entry)
+        return NULL;
+
+    if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID) {
+        nm_assert((NMP_OBJECT_GET_TYPE(needle) == NMP_OBJECT_TYPE_IP4_ROUTE
+                   && nm_platform_ip4_route_cmp(NMP_OBJECT_CAST_IP4_ROUTE(entry->obj),
+                                                NMP_OBJECT_CAST_IP4_ROUTE(needle),
+                                                cmp_type)
+                          == 0)
+                  || (NMP_OBJECT_GET_TYPE(needle) == NMP_OBJECT_TYPE_IP6_ROUTE
+                      && nm_platform_ip6_route_cmp(NMP_OBJECT_CAST_IP6_ROUTE(entry->obj),
+                                                   NMP_OBJECT_CAST_IP6_ROUTE(needle),
+                                                   cmp_type)
+                             == 0));
+    } else {
+        if (NMP_OBJECT_GET_TYPE(needle) == NMP_OBJECT_TYPE_IP4_ROUTE) {
+            if (nm_platform_ip4_route_cmp(NMP_OBJECT_CAST_IP4_ROUTE(entry->obj),
+                                          NMP_OBJECT_CAST_IP4_ROUTE(needle),
+                                          cmp_type)
+                != 0)
+                return NULL;
+        } else {
+            if (nm_platform_ip6_route_cmp(NMP_OBJECT_CAST_IP6_ROUTE(entry->obj),
+                                          NMP_OBJECT_CAST_IP6_ROUTE(needle),
+                                          cmp_type)
+                != 0)
+                return NULL;
+        }
+    }
+    return entry;
 }
 
 /*****************************************************************************/
 
-NM_GOBJECT_PROPERTIES_DEFINE (NMIP4Config,
-	PROP_MULTI_IDX,
-	PROP_IFINDEX,
-	PROP_ADDRESS_DATA,
-	PROP_ADDRESSES,
-	PROP_ROUTE_DATA,
-	PROP_ROUTES,
-	PROP_GATEWAY,
-	PROP_NAMESERVER_DATA,
-	PROP_NAMESERVERS,
-	PROP_DOMAINS,
-	PROP_SEARCHES,
-	PROP_DNS_OPTIONS,
-	PROP_WINS_SERVER_DATA,
-	PROP_WINS_SERVERS,
-	PROP_DNS_PRIORITY,
-);
+NM_GOBJECT_PROPERTIES_DEFINE(NMIP4Config,
+                             PROP_MULTI_IDX,
+                             PROP_IFINDEX,
+                             PROP_ADDRESS_DATA,
+                             PROP_ADDRESSES,
+                             PROP_ROUTE_DATA,
+                             PROP_ROUTES,
+                             PROP_GATEWAY,
+                             PROP_NAMESERVER_DATA,
+                             PROP_NAMESERVERS,
+                             PROP_DOMAINS,
+                             PROP_SEARCHES,
+                             PROP_DNS_OPTIONS,
+                             PROP_WINS_SERVER_DATA,
+                             PROP_WINS_SERVERS,
+                             PROP_DNS_PRIORITY, );
 
 typedef struct {
-	bool metered:1;
-	guint32 mtu;
-	int ifindex;
-	NMIPConfigSource mtu_source;
-	int dns_priority;
-	NMSettingConnectionMdns mdns;
-	NMSettingConnectionLlmnr llmnr;
-	GArray *nameservers;
-	GPtrArray *domains;
-	GPtrArray *searches;
-	GPtrArray *dns_options;
-	GArray *nis;
-	char *nis_domain;
-	GArray *wins;
-	GVariant *address_data_variant;
-	GVariant *addresses_variant;
-	GVariant *route_data_variant;
-	GVariant *routes_variant;
-	NMDedupMultiIndex *multi_idx;
-	const NMPObject *best_default_route;
-	union {
-		NMIPConfigDedupMultiIdxType idx_ip4_addresses_;
-		NMDedupMultiIdxType idx_ip4_addresses;
-	};
-	union {
-		NMIPConfigDedupMultiIdxType idx_ip4_routes_;
-		NMDedupMultiIdxType idx_ip4_routes;
-	};
-	NMIPConfigFlags config_flags;
+    bool                     metered : 1;
+    guint32                  mtu;
+    int                      ifindex;
+    NMIPConfigSource         mtu_source;
+    int                      dns_priority;
+    NMSettingConnectionMdns  mdns;
+    NMSettingConnectionLlmnr llmnr;
+    GArray *                 nameservers;
+    GPtrArray *              domains;
+    GPtrArray *              searches;
+    GPtrArray *              dns_options;
+    GArray *                 nis;
+    char *                   nis_domain;
+    GArray *                 wins;
+    GVariant *               address_data_variant;
+    GVariant *               addresses_variant;
+    GVariant *               route_data_variant;
+    GVariant *               routes_variant;
+    NMDedupMultiIndex *      multi_idx;
+    const NMPObject *        best_default_route;
+    union {
+        NMIPConfigDedupMultiIdxType idx_ip4_addresses_;
+        NMDedupMultiIdxType         idx_ip4_addresses;
+    };
+    union {
+        NMIPConfigDedupMultiIdxType idx_ip4_routes_;
+        NMDedupMultiIdxType         idx_ip4_routes;
+    };
+    NMIPConfigFlags config_flags;
 } NMIP4ConfigPrivate;
 
 struct _NMIP4Config {
-	NMDBusObject parent;
-	NMIP4ConfigPrivate _priv;
+    NMIPConfig         parent;
+    NMIP4ConfigPrivate _priv;
 };
 
 struct _NMIP4ConfigClass {
-	NMDBusObjectClass parent;
+    NMIPConfigClass parent;
 };
 
-G_DEFINE_TYPE (NMIP4Config, nm_ip4_config, NM_TYPE_DBUS_OBJECT)
+G_DEFINE_TYPE(NMIP4Config, nm_ip4_config, NM_TYPE_IP_CONFIG)
 
 #define NM_IP4_CONFIG_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMIP4Config, NM_IS_IP4_CONFIG)
 
 /*****************************************************************************/
 
-static void _add_address (NMIP4Config *self, const NMPObject *obj_new, const NMPlatformIP4Address *new);
-static void _add_route (NMIP4Config *self, const NMPObject *obj_new, const NMPlatformIP4Route *new, const NMPObject **out_obj_new);
-static const NMDedupMultiEntry *_lookup_route (const NMIP4Config *self,
-                                               const NMPObject *needle,
-                                               NMPlatformIPRouteCmpType cmp_type);
+static void
+_add_address(NMIP4Config *self, const NMPObject *obj_new, const NMPlatformIP4Address *new);
+static void _add_route(NMIP4Config *    self,
+                       const NMPObject *obj_new,
+                       const NMPlatformIP4Route *new,
+                       const NMPObject **out_obj_new);
+static const NMDedupMultiEntry *
+_lookup_route(const NMIP4Config *self, const NMPObject *needle, NMPlatformIPRouteCmpType cmp_type);
 
 /*****************************************************************************/
 
 int
-nm_ip4_config_get_ifindex (const NMIP4Config *self)
+nm_ip4_config_get_ifindex(const NMIP4Config *self)
 {
-	return NM_IP4_CONFIG_GET_PRIVATE (self)->ifindex;
+    return NM_IP4_CONFIG_GET_PRIVATE(self)->ifindex;
 }
 
 NMDedupMultiIndex *
-nm_ip4_config_get_multi_idx (const NMIP4Config *self)
+nm_ip4_config_get_multi_idx(const NMIP4Config *self)
 {
-	return NM_IP4_CONFIG_GET_PRIVATE (self)->multi_idx;
-}
-
-/*****************************************************************************/
-
-static gboolean
-_ipv4_is_zeronet (in_addr_t network)
-{
-	/* Same as ipv4_is_zeronet() from kernel's include/linux/in.h. */
-	return (network & htonl(0xff000000)) == htonl(0x00000000);
+    return NM_IP4_CONFIG_GET_PRIVATE(self)->multi_idx;
 }
 
 /*****************************************************************************/
 
 const NMDedupMultiHeadEntry *
-nm_ip4_config_lookup_addresses (const NMIP4Config *self)
+nm_ip4_config_lookup_addresses(const NMIP4Config *self)
 {
-	const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+    const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
 
-	return nm_dedup_multi_index_lookup_head (priv->multi_idx,
-	                                         &priv->idx_ip4_addresses,
-	                                         NULL);
+    return nm_dedup_multi_index_lookup_head(priv->multi_idx, &priv->idx_ip4_addresses, NULL);
 }
 
 void
-nm_ip_config_iter_ip4_address_init (NMDedupMultiIter *ipconf_iter, const NMIP4Config *self)
+nm_ip_config_iter_ip4_address_init(NMDedupMultiIter *ipconf_iter, const NMIP4Config *self)
 {
-	g_return_if_fail (NM_IS_IP4_CONFIG (self));
-	nm_dedup_multi_iter_init (ipconf_iter, nm_ip4_config_lookup_addresses (self));
+    g_return_if_fail(NM_IS_IP4_CONFIG(self));
+    nm_dedup_multi_iter_init(ipconf_iter, nm_ip4_config_lookup_addresses(self));
 }
 
 /*****************************************************************************/
 
 const NMDedupMultiHeadEntry *
-nm_ip4_config_lookup_routes (const NMIP4Config *self)
+nm_ip4_config_lookup_routes(const NMIP4Config *self)
 {
-	const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+    const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
 
-	return nm_dedup_multi_index_lookup_head (priv->multi_idx,
-	                                         &priv->idx_ip4_routes,
-	                                         NULL);
+    return nm_dedup_multi_index_lookup_head(priv->multi_idx, &priv->idx_ip4_routes, NULL);
 }
 
 void
-nm_ip_config_iter_ip4_route_init (NMDedupMultiIter *ipconf_iter, const NMIP4Config *self)
+nm_ip_config_iter_ip4_route_init(NMDedupMultiIter *ipconf_iter, const NMIP4Config *self)
 {
-	nm_assert (NM_IS_IP4_CONFIG (self));
-	nm_dedup_multi_iter_init (ipconf_iter, nm_ip4_config_lookup_routes (self));
+    nm_assert(NM_IS_IP4_CONFIG(self));
+    nm_dedup_multi_iter_init(ipconf_iter, nm_ip4_config_lookup_routes(self));
 }
 
 /*****************************************************************************/
 
 const NMPObject *
-_nm_ip_config_best_default_route_find_better (const NMPObject *obj_cur, const NMPObject *obj_cmp)
-{
-	nm_assert (   !obj_cur
-	           || NM_IN_SET (NMP_OBJECT_GET_TYPE (obj_cur), NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE));
-	nm_assert (   !obj_cmp
-	           || (   !obj_cur
-	               && NM_IN_SET (NMP_OBJECT_GET_TYPE (obj_cmp), NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE))
-	           || NMP_OBJECT_GET_TYPE (obj_cur) == NMP_OBJECT_GET_TYPE (obj_cmp));
-	nm_assert (   !obj_cur
-	           || nm_ip_config_best_default_route_is (obj_cur));
-
-	/* assumes that @obj_cur is already the best default route (or NULL). It checks whether
-	 * @obj_cmp is also a default route and returns the best of both. */
-	if (   obj_cmp
-	    && nm_ip_config_best_default_route_is (obj_cmp)) {
-		guint32 metric_cur, metric_cmp;
-
-		if (!obj_cur)
-			return obj_cmp;
-
-		metric_cur = NMP_OBJECT_CAST_IP_ROUTE (obj_cur)->metric;
-		metric_cmp = NMP_OBJECT_CAST_IP_ROUTE (obj_cmp)->metric;
-
-		if (metric_cmp < metric_cur)
-			return obj_cmp;
-
-		if (metric_cmp == metric_cur) {
-			int c;
-
-			/* Routes have the same metric. We still want to deterministically
-			 * prefer one or the other. It's important to consistently choose one
-			 * or the other, so that the order doesn't matter how routes are added
-			 * (and merged). */
-			c = nmp_object_cmp (obj_cur, obj_cmp);
-			if (c != 0)
-				return c < 0 ? obj_cur : obj_cmp;
-
-			/* as last resort, compare pointers. */
-			if (obj_cmp < obj_cur)
-				return obj_cmp;
-		}
-	}
-	return obj_cur;
+_nm_ip_config_best_default_route_find_better(const NMPObject *obj_cur, const NMPObject *obj_cmp)
+{
+    nm_assert(!obj_cur
+              || NM_IN_SET(NMP_OBJECT_GET_TYPE(obj_cur),
+                           NMP_OBJECT_TYPE_IP4_ROUTE,
+                           NMP_OBJECT_TYPE_IP6_ROUTE));
+    nm_assert(!obj_cmp
+              || (!obj_cur
+                  && NM_IN_SET(NMP_OBJECT_GET_TYPE(obj_cmp),
+                               NMP_OBJECT_TYPE_IP4_ROUTE,
+                               NMP_OBJECT_TYPE_IP6_ROUTE))
+              || NMP_OBJECT_GET_TYPE(obj_cur) == NMP_OBJECT_GET_TYPE(obj_cmp));
+    nm_assert(!obj_cur || nmp_object_ip_route_is_best_defaut_route(obj_cur));
+
+    /* assumes that @obj_cur is already the best default route (or NULL). It checks whether
+     * @obj_cmp is also a default route and returns the best of both. */
+    if (obj_cmp && nmp_object_ip_route_is_best_defaut_route(obj_cmp)) {
+        guint32 metric_cur, metric_cmp;
+
+        if (!obj_cur)
+            return obj_cmp;
+
+        metric_cur = NMP_OBJECT_CAST_IP_ROUTE(obj_cur)->metric;
+        metric_cmp = NMP_OBJECT_CAST_IP_ROUTE(obj_cmp)->metric;
+
+        if (metric_cmp < metric_cur)
+            return obj_cmp;
+
+        if (metric_cmp == metric_cur) {
+            int c;
+
+            /* Routes have the same metric. We still want to deterministically
+             * prefer one or the other. It's important to consistently choose one
+             * or the other, so that the order doesn't matter how routes are added
+             * (and merged). */
+            c = nmp_object_cmp(obj_cur, obj_cmp);
+            if (c != 0)
+                return c < 0 ? obj_cur : obj_cmp;
+
+            /* as last resort, compare pointers. */
+            if (obj_cmp < obj_cur)
+                return obj_cmp;
+        }
+    }
+    return obj_cur;
 }
 
 gboolean
-_nm_ip_config_best_default_route_set (const NMPObject **best_default_route, const NMPObject *new_candidate)
+_nm_ip_config_best_default_route_merge(const NMPObject **best_default_route,
+                                       const NMPObject * new_candidate)
 {
-	if (new_candidate == *best_default_route)
-		return FALSE;
-	nmp_object_ref (new_candidate);
-	nm_clear_nmp_object (best_default_route);
-	*best_default_route = new_candidate;
-	return TRUE;
-}
-
-gboolean
-_nm_ip_config_best_default_route_merge (const NMPObject **best_default_route, const NMPObject *new_candidate)
-{
-	new_candidate = _nm_ip_config_best_default_route_find_better (*best_default_route,
-	                                                              new_candidate);
-	return _nm_ip_config_best_default_route_set (best_default_route, new_candidate);
+    new_candidate =
+        _nm_ip_config_best_default_route_find_better(*best_default_route, new_candidate);
+    return nmp_object_ref_set(best_default_route, new_candidate);
 }
 
 const NMPObject *
-nm_ip4_config_best_default_route_get (const NMIP4Config *self)
+nm_ip4_config_best_default_route_get(const NMIP4Config *self)
 {
-	g_return_val_if_fail (NM_IS_IP4_CONFIG (self), NULL);
+    g_return_val_if_fail(NM_IS_IP4_CONFIG(self), NULL);
 
-	return NM_IP4_CONFIG_GET_PRIVATE (self)->best_default_route;
+    return NM_IP4_CONFIG_GET_PRIVATE(self)->best_default_route;
 }
 
 const NMPObject *
-_nm_ip4_config_best_default_route_find (const NMIP4Config *self)
+_nm_ip4_config_best_default_route_find(const NMIP4Config *self)
 {
-	NMDedupMultiIter ipconf_iter;
-	const NMPObject *new_best_default_route = NULL;
+    NMDedupMultiIter ipconf_iter;
+    const NMPObject *new_best_default_route = NULL;
 
-	nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, self, NULL) {
-		new_best_default_route = _nm_ip_config_best_default_route_find_better (new_best_default_route,
-		                                                                       ipconf_iter.current->obj);
-	}
-	return new_best_default_route;
+    nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, self, NULL) {
+        new_best_default_route =
+            _nm_ip_config_best_default_route_find_better(new_best_default_route,
+                                                         ipconf_iter.current->obj);
+    }
+    return new_best_default_route;
 }
 
 in_addr_t
-nmtst_ip4_config_get_gateway (NMIP4Config *config)
+nmtst_ip4_config_get_gateway(NMIP4Config *config)
 {
-	const NMPObject *rt;
+    const NMPObject *rt;
 
-	g_assert (NM_IS_IP4_CONFIG (config));
+    g_assert(NM_IS_IP4_CONFIG(config));
 
-	rt = nm_ip4_config_best_default_route_get (config);
-	if (!rt)
-		return 0;
-	return NMP_OBJECT_CAST_IP4_ROUTE (rt)->gateway;
+    rt = nm_ip4_config_best_default_route_get(config);
+    if (!rt)
+        return 0;
+    return NMP_OBJECT_CAST_IP4_ROUTE(rt)->gateway;
 }
 
 /*****************************************************************************/
 
 static void
-_notify_addresses (NMIP4Config *self)
+_notify_addresses(NMIP4Config *self)
 {
-	NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+    NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
 
-	nm_clear_g_variant (&priv->address_data_variant);
-	nm_clear_g_variant (&priv->addresses_variant);
-	nm_gobject_notify_together (self, PROP_ADDRESS_DATA,
-	                                  PROP_ADDRESSES);
+    nm_clear_g_variant(&priv->address_data_variant);
+    nm_clear_g_variant(&priv->addresses_variant);
+    nm_gobject_notify_together(self, PROP_ADDRESS_DATA, PROP_ADDRESSES);
 }
 
 static void
-_notify_routes (NMIP4Config *self)
+_notify_routes(NMIP4Config *self)
 {
-	NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+    NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
 
-	nm_assert (priv->best_default_route == _nm_ip4_config_best_default_route_find (self));
-	nm_clear_g_variant (&priv->route_data_variant);
-	nm_clear_g_variant (&priv->routes_variant);
-	nm_gobject_notify_together (self, PROP_ROUTE_DATA,
-	                                  PROP_ROUTES);
+    nm_assert(priv->best_default_route == _nm_ip4_config_best_default_route_find(self));
+    nm_clear_g_variant(&priv->route_data_variant);
+    nm_clear_g_variant(&priv->routes_variant);
+    nm_gobject_notify_together(self, PROP_ROUTE_DATA, PROP_ROUTES);
 }
 
 /*****************************************************************************/
 
 static int
-_addresses_sort_cmp_get_prio (in_addr_t addr)
-{
-	if (nm_utils_ip4_address_is_link_local (addr))
-		return 0;
-	return 1;
-}
-
-static int
-_addresses_sort_cmp (gconstpointer a, gconstpointer b, gpointer user_data)
+sort_captured_addresses(const CList *lst_a, const CList *lst_b, gconstpointer user_data)
 {
-	int p1, p2;
-	const NMPlatformIP4Address *a1 = NMP_OBJECT_CAST_IP4_ADDRESS (*((const NMPObject **) a));
-	const NMPlatformIP4Address *a2 = NMP_OBJECT_CAST_IP4_ADDRESS (*((const NMPObject **) b));
-	guint32 n1, n2;
-
-	nm_assert (a1);
-	nm_assert (a2);
-
-	/* Sort by address type. For example link local will
-	 * be sorted *after* a global address. */
-	p1 = _addresses_sort_cmp_get_prio (a1->address);
-	p2 = _addresses_sort_cmp_get_prio (a2->address);
-	if (p1 != p2)
-		return p1 > p2 ? -1 : 1;
-
-	/* Sort the addresses based on their source. */
-	if (a1->addr_source != a2->addr_source)
-		return a1->addr_source > a2->addr_source ? -1 : 1;
+    const NMPlatformIP4Address *addr_a =
+        NMP_OBJECT_CAST_IP4_ADDRESS(c_list_entry(lst_a, NMDedupMultiEntry, lst_entries)->obj);
+    const NMPlatformIP4Address *addr_b =
+        NMP_OBJECT_CAST_IP4_ADDRESS(c_list_entry(lst_b, NMDedupMultiEntry, lst_entries)->obj);
 
-	if ((a1->label[0] == '\0') != (a2->label[0] == '\0'))
-		return (a1->label[0] == '\0') ? -1 : 1;
+    nm_assert(addr_a);
+    nm_assert(addr_b);
 
-	/* 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));
-}
-
-/*****************************************************************************/
-
-static int
-sort_captured_addresses (const CList *lst_a, const CList *lst_b, gconstpointer user_data)
-{
-	const NMPlatformIP4Address *addr_a = NMP_OBJECT_CAST_IP4_ADDRESS (c_list_entry (lst_a, NMDedupMultiEntry, lst_entries)->obj);
-	const NMPlatformIP4Address *addr_b = NMP_OBJECT_CAST_IP4_ADDRESS (c_list_entry (lst_b, NMDedupMultiEntry, lst_entries)->obj);
-
-	nm_assert (addr_a);
-	nm_assert (addr_b);
-
-	/* Primary addresses first */
-	return NM_FLAGS_HAS (addr_a->n_ifa_flags, IFA_F_SECONDARY) -
-	       NM_FLAGS_HAS (addr_b->n_ifa_flags, IFA_F_SECONDARY);
+    /* Primary addresses first */
+    return NM_FLAGS_HAS(addr_a->n_ifa_flags, IFA_F_SECONDARY)
+           - NM_FLAGS_HAS(addr_b->n_ifa_flags, IFA_F_SECONDARY);
 }
 
 NMIP4Config *
-nm_ip4_config_clone (const NMIP4Config *self)
+nm_ip4_config_clone(const NMIP4Config *self)
 {
-	NMIP4Config *copy;
+    NMIP4Config *copy;
 
-	copy = nm_ip4_config_new (nm_ip4_config_get_multi_idx (self), -1);
-	nm_ip4_config_replace (copy, self, NULL);
+    copy = nm_ip4_config_new(nm_ip4_config_get_multi_idx(self), -1);
+    nm_ip4_config_replace(copy, self, NULL);
 
-	return copy;
+    return copy;
 }
 
 NMIP4Config *
-nm_ip4_config_capture (NMDedupMultiIndex *multi_idx, NMPlatform *platform, int ifindex)
-{
-	NMIP4Config *self;
-	NMIP4ConfigPrivate *priv;
-	const NMDedupMultiHeadEntry *head_entry;
-	NMDedupMultiIter iter;
-	const NMPObject *plobj = NULL;
-
-	nm_assert (ifindex > 0);
-
-	/* Slaves have no IP configuration */
-	if (nm_platform_link_get_master (platform, ifindex) > 0)
-		return NULL;
-
-	self = nm_ip4_config_new (multi_idx, ifindex);
-	priv = NM_IP4_CONFIG_GET_PRIVATE (self);
-
-	head_entry = nm_platform_lookup_object (platform,
-	                                        NMP_OBJECT_TYPE_IP4_ADDRESS,
-	                                        ifindex);
-	if (head_entry) {
-		nmp_cache_iter_for_each (&iter, head_entry, &plobj) {
-			if (!_nm_ip_config_add_obj (priv->multi_idx,
-			                            &priv->idx_ip4_addresses_,
-			                            ifindex,
-			                            plobj,
-			                            NULL,
-			                            FALSE,
-			                            TRUE,
-			                            NULL,
-			                            NULL))
-				nm_assert_not_reached ();
-		}
-		head_entry = nm_ip4_config_lookup_addresses (self);
-		nm_assert (head_entry);
-		nm_dedup_multi_head_entry_sort (head_entry,
-		                                sort_captured_addresses,
-		                                NULL);
-		_notify_addresses (self);
-	}
-
-	head_entry = nm_platform_lookup_object (platform,
-	                                        NMP_OBJECT_TYPE_IP4_ROUTE,
-	                                        ifindex);
-
-	/* Extract gateway from default route */
-	nmp_cache_iter_for_each (&iter, head_entry, &plobj)
-		_add_route (self, plobj, NULL, NULL);
-
-	return self;
+nm_ip4_config_capture(NMDedupMultiIndex *multi_idx, NMPlatform *platform, int ifindex)
+{
+    NMIP4Config *                self;
+    NMIP4ConfigPrivate *         priv;
+    const NMDedupMultiHeadEntry *head_entry;
+    NMDedupMultiIter             iter;
+    const NMPObject *            plobj = NULL;
+
+    nm_assert(ifindex > 0);
+
+    /* Slaves have no IP configuration */
+    if (nm_platform_link_get_master(platform, ifindex) > 0)
+        return NULL;
+
+    self = nm_ip4_config_new(multi_idx, ifindex);
+    priv = NM_IP4_CONFIG_GET_PRIVATE(self);
+
+    head_entry = nm_platform_lookup_object(platform, NMP_OBJECT_TYPE_IP4_ADDRESS, ifindex);
+    if (head_entry) {
+        nmp_cache_iter_for_each (&iter, head_entry, &plobj) {
+            if (!_nm_ip_config_add_obj(priv->multi_idx,
+                                       &priv->idx_ip4_addresses_,
+                                       ifindex,
+                                       plobj,
+                                       NULL,
+                                       FALSE,
+                                       TRUE,
+                                       NULL,
+                                       NULL))
+                nm_assert_not_reached();
+        }
+        head_entry = nm_ip4_config_lookup_addresses(self);
+        nm_assert(head_entry);
+        nm_dedup_multi_head_entry_sort(head_entry, sort_captured_addresses, NULL);
+        _notify_addresses(self);
+    }
+
+    head_entry = nm_platform_lookup_object(platform, NMP_OBJECT_TYPE_IP4_ROUTE, ifindex);
+
+    /* Extract gateway from default route */
+    nmp_cache_iter_for_each (&iter, head_entry, &plobj)
+        _add_route(self, plobj, NULL, NULL);
+
+    return self;
 }
 
 void
-nm_ip4_config_update_routes_metric (NMIP4Config *self, gint64 metric)
-{
-	gs_free NMPlatformIP4Route *routes = NULL;
-	gboolean need_update = FALSE;
-	const NMPlatformIP4Route *r;
-	NMDedupMultiIter iter;
-	guint num = 0, i = 0;
-
-	nm_ip_config_iter_ip4_route_for_each (&iter, self, &r) {
-		if (r->metric != metric)
-			need_update = TRUE;
-		num++;
-	}
-	if (!need_update)
-		return;
-
-	routes = g_new (NMPlatformIP4Route, num);
-	nm_ip_config_iter_ip4_route_for_each (&iter, self, &r) {
-		routes[i] = *r;
-		routes[i].metric = metric;
-		i++;
-	}
-
-	g_object_freeze_notify (G_OBJECT (self));
-	nm_ip4_config_reset_routes (self);
-	for (i = 0; i < num; i++)
-		nm_ip4_config_add_route (self, &routes[i], NULL);
-	g_object_thaw_notify (G_OBJECT (self));
-}
-
-static void
-_add_local_route_from_addr4 (NMIP4Config *               self,
-                             const NMPlatformIP4Address *addr,
-                             int                         ifindex,
-                             guint32                     route_table,
-                             gboolean                    is_vrf)
-{
-	nm_auto_nmpobj NMPObject *r = NULL;
-	NMPlatformIP4Route *route;
-
-	r = nmp_object_new (NMP_OBJECT_TYPE_IP4_ROUTE, NULL);
-	route = NMP_OBJECT_CAST_IP4_ROUTE (r);
-	route->ifindex = ifindex;
-	route->rt_source = NM_IP_CONFIG_SOURCE_KERNEL;
-	route->network = addr->address;
-	route->plen = 32;
-	route->pref_src = addr->address;
-	route->type_coerced = nm_platform_route_type_coerce (RTN_LOCAL);
-	route->scope_inv = nm_platform_route_scope_inv (RT_SCOPE_HOST);
-	route->table_coerced = nm_platform_route_table_coerce (is_vrf ? route_table : RT_TABLE_LOCAL);
-
-	_add_route (self, r, NULL, NULL);
+nm_ip4_config_update_routes_metric(NMIP4Config *self, gint64 metric)
+{
+    gs_free NMPlatformIP4Route *routes      = NULL;
+    gboolean                    need_update = FALSE;
+    const NMPlatformIP4Route *  r;
+    NMDedupMultiIter            iter;
+    guint                       num = 0, i = 0;
+
+    nm_ip_config_iter_ip4_route_for_each (&iter, self, &r) {
+        if (r->metric != metric)
+            need_update = TRUE;
+        num++;
+    }
+    if (!need_update)
+        return;
+
+    routes = g_new(NMPlatformIP4Route, num);
+    nm_ip_config_iter_ip4_route_for_each (&iter, self, &r) {
+        routes[i]        = *r;
+        routes[i].metric = metric;
+        i++;
+    }
+
+    g_object_freeze_notify(G_OBJECT(self));
+    nm_ip4_config_reset_routes(self);
+    for (i = 0; i < num; i++)
+        nm_ip4_config_add_route(self, &routes[i], NULL);
+    g_object_thaw_notify(G_OBJECT(self));
 }
 
 void
-nm_ip4_config_add_dependent_routes (NMIP4Config *self,
-                                    guint32      route_table,
-                                    guint32      route_metric,
-                                    gboolean     is_vrf,
-                                    GPtrArray ** out_ip4_dev_route_blacklist)
-{
-	GPtrArray *ip4_dev_route_blacklist = NULL;
-	const NMPlatformIP4Address *my_addr;
-	const NMPlatformIP4Route *my_route;
-	int ifindex;
-	NMDedupMultiIter iter;
-
-	g_return_if_fail (NM_IS_IP4_CONFIG (self));
-
-	ifindex = nm_ip4_config_get_ifindex (self);
-	g_return_if_fail (ifindex > 0);
-
-	/* For IPv6 slaac, we explicitly add the device-routes (onlink) to NMIP6Config.
-	 * As we don't do that for IPv4 (and manual IPv6 addresses), add them explicitly. */
-
-	nm_ip_config_iter_ip4_address_for_each (&iter, self, &my_addr) {
-		nm_auto_nmpobj NMPObject *r = NULL;
-		NMPlatformIP4Route *route;
-		in_addr_t network;
-
-		if (my_addr->plen == 0)
-			continue;
-
-		nm_assert (my_addr->plen <= 32);
-
-		/* The destination network depends on the peer-address. */
-		network = nm_utils_ip4_address_clear_host_address (my_addr->peer_address, my_addr->plen);
-
-		if (my_addr->external)
-			continue;
-
-		_add_local_route_from_addr4 (self, my_addr, ifindex, route_table, is_vrf);
-
-		if (_ipv4_is_zeronet (network)) {
-			/* Kernel doesn't add device-routes for destinations that
-			 * start with 0.x.y.z. Skip them. */
-			continue;
-		}
-
-		if (   my_addr->plen == 32
-		    && my_addr->address == my_addr->peer_address) {
-			/* Kernel doesn't add device-routes for /32 addresses unless
-			 * they have a peer. */
-			continue;
-		}
-
-		r = nmp_object_new (NMP_OBJECT_TYPE_IP4_ROUTE, NULL);
-		route = NMP_OBJECT_CAST_IP4_ROUTE (r);
-
-		route->ifindex = ifindex;
-		route->rt_source = NM_IP_CONFIG_SOURCE_KERNEL;
-		route->network = network;
-		route->plen = my_addr->plen;
-		route->pref_src = my_addr->address;
-		route->table_coerced = nm_platform_route_table_coerce (route_table);
-		route->metric = route_metric;
-		route->scope_inv = nm_platform_route_scope_inv (NM_RT_SCOPE_LINK);
-
-		nm_platform_ip_route_normalize (AF_INET, (NMPlatformIPRoute *) route);
-
-		if (_lookup_route (self,
-		                   r,
-		                   NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID)) {
-			/* we already track this route. Don't add it again. */
-		} else
-			_add_route (self, r, NULL, NULL);
-
-		if (   out_ip4_dev_route_blacklist
-		    && (   route_table != RT_TABLE_MAIN
-		        || route_metric != NM_PLATFORM_ROUTE_METRIC_IP4_DEVICE_ROUTE)) {
-			nm_auto_nmpobj NMPObject *r_dev = NULL;
-
-			r_dev = nmp_object_clone (r, FALSE);
-			route = NMP_OBJECT_CAST_IP4_ROUTE (r_dev);
-			route->table_coerced = nm_platform_route_table_coerce (RT_TABLE_MAIN);
-			route->metric = NM_PLATFORM_ROUTE_METRIC_IP4_DEVICE_ROUTE;
-
-			nm_platform_ip_route_normalize (AF_INET, (NMPlatformIPRoute *) route);
-
-			if (_lookup_route (self,
-			                   r_dev,
-			                   NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID)) {
-				/* we track such a route explicitly. Don't blacklist it. */
-			} else {
-				if (!ip4_dev_route_blacklist)
-					ip4_dev_route_blacklist = g_ptr_array_new_with_free_func ((GDestroyNotify) nmp_object_unref);
-
-				g_ptr_array_add (ip4_dev_route_blacklist,
-				                 g_steal_pointer (&r_dev));
-			}
-		}
-	}
+nm_ip4_config_add_dependent_routes(NMIP4Config *self,
+                                   guint32      route_table,
+                                   guint32      route_metric,
+                                   gboolean     is_vrf,
+                                   GPtrArray ** out_ip4_dev_route_blacklist)
+{
+    GPtrArray *                 ip4_dev_route_blacklist = NULL;
+    const NMPlatformIP4Address *my_addr;
+    const NMPlatformIP4Route *  my_route;
+    int                         ifindex;
+    NMDedupMultiIter            iter;
+
+    g_return_if_fail(NM_IS_IP4_CONFIG(self));
+
+    ifindex = nm_ip4_config_get_ifindex(self);
+    g_return_if_fail(ifindex > 0);
+
+    /* For IPv6 slaac, we explicitly add the device-routes (onlink) to NMIP6Config.
+     * As we don't do that for IPv4 (and manual IPv6 addresses), add them explicitly. */
+
+    nm_ip_config_iter_ip4_address_for_each (&iter, self, &my_addr) {
+        nm_auto_nmpobj NMPObject *r = NULL;
+        NMPlatformIP4Route *      route;
+        in_addr_t                 network;
+
+        if (my_addr->plen == 0)
+            continue;
+
+        nm_assert(my_addr->plen <= 32);
+
+        /* The destination network depends on the peer-address. */
+        network = nm_utils_ip4_address_clear_host_address(my_addr->peer_address, my_addr->plen);
+
+        if (my_addr->external)
+            continue;
+
+        /* Pre-generate local route added by kernel */
+        r                   = nmp_object_new(NMP_OBJECT_TYPE_IP4_ROUTE, NULL);
+        route               = NMP_OBJECT_CAST_IP4_ROUTE(r);
+        route->ifindex      = ifindex;
+        route->rt_source    = NM_IP_CONFIG_SOURCE_KERNEL;
+        route->network      = my_addr->address;
+        route->plen         = 32;
+        route->pref_src     = my_addr->address;
+        route->type_coerced = nm_platform_route_type_coerce(RTN_LOCAL);
+        route->scope_inv    = nm_platform_route_scope_inv(RT_SCOPE_HOST);
+        route->table_coerced =
+            nm_platform_route_table_coerce(is_vrf ? route_table : RT_TABLE_LOCAL);
+        _add_route(self, r, NULL, NULL);
+        nm_clear_pointer(&r, nmp_object_unref);
+
+        if (nm_utils_ip4_address_is_zeronet(network)) {
+            /* Kernel doesn't add device-routes for destinations that
+             * start with 0.x.y.z. Skip them. */
+            continue;
+        }
+
+        if (my_addr->plen == 32 && my_addr->address == my_addr->peer_address) {
+            /* Kernel doesn't add device-routes for /32 addresses unless
+             * they have a peer. */
+            continue;
+        }
+
+        r     = nmp_object_new(NMP_OBJECT_TYPE_IP4_ROUTE, NULL);
+        route = NMP_OBJECT_CAST_IP4_ROUTE(r);
+
+        route->ifindex       = ifindex;
+        route->rt_source     = NM_IP_CONFIG_SOURCE_KERNEL;
+        route->network       = network;
+        route->plen          = my_addr->plen;
+        route->pref_src      = my_addr->address;
+        route->table_coerced = nm_platform_route_table_coerce(route_table);
+        route->metric        = route_metric;
+        route->scope_inv     = nm_platform_route_scope_inv(NM_RT_SCOPE_LINK);
+
+        nm_platform_ip_route_normalize(AF_INET, (NMPlatformIPRoute *) route);
+
+        if (_lookup_route(self, r, NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID)) {
+            /* we already track this route. Don't add it again. */
+        } else
+            _add_route(self, r, NULL, NULL);
+
+        if (out_ip4_dev_route_blacklist
+            && (route_table != RT_TABLE_MAIN
+                || route_metric != NM_PLATFORM_ROUTE_METRIC_IP4_DEVICE_ROUTE)) {
+            nm_auto_nmpobj NMPObject *r_dev = NULL;
+
+            r_dev                = nmp_object_clone(r, FALSE);
+            route                = NMP_OBJECT_CAST_IP4_ROUTE(r_dev);
+            route->table_coerced = nm_platform_route_table_coerce(RT_TABLE_MAIN);
+            route->metric        = NM_PLATFORM_ROUTE_METRIC_IP4_DEVICE_ROUTE;
+
+            nm_platform_ip_route_normalize(AF_INET, (NMPlatformIPRoute *) route);
+
+            if (_lookup_route(self, r_dev, NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID)) {
+                /* we track such a route explicitly. Don't blacklist it. */
+            } else {
+                if (!ip4_dev_route_blacklist)
+                    ip4_dev_route_blacklist =
+                        g_ptr_array_new_with_free_func((GDestroyNotify) nmp_object_unref);
+
+                g_ptr_array_add(ip4_dev_route_blacklist, g_steal_pointer(&r_dev));
+            }
+        }
+    }
 
 again:
-	nm_ip_config_iter_ip4_route_for_each (&iter, self, &my_route) {
-		NMPlatformIP4Route rt;
+    nm_ip_config_iter_ip4_route_for_each (&iter, self, &my_route) {
+        NMPlatformIP4Route rt;
 
-		if (   !NM_PLATFORM_IP_ROUTE_IS_DEFAULT (my_route)
-		    || my_route->gateway == 0
-		    || NM_IS_IP_CONFIG_SOURCE_RTPROT (my_route->rt_source)
-		    || nm_ip4_config_get_direct_route_for_host (self,
-		                                                my_route->gateway,
-		                                                nm_platform_route_table_uncoerce (my_route->table_coerced, TRUE)))
-			continue;
+        if (!NM_PLATFORM_IP_ROUTE_IS_DEFAULT(my_route) || my_route->gateway == 0
+            || NM_IS_IP_CONFIG_SOURCE_RTPROT(my_route->rt_source)
+            || nm_ip4_config_get_direct_route_for_host(
+                self,
+                my_route->gateway,
+                nm_platform_route_table_uncoerce(my_route->table_coerced, TRUE)))
+            continue;
 
-		rt = *my_route;
-		rt.network = my_route->gateway;
-		rt.plen = 32;
-		rt.gateway = 0;
-		_add_route (self, NULL, &rt, NULL);
-		/* adding the route might have invalidated the iteration. Start again. */
-		goto again;
-	}
+        rt         = *my_route;
+        rt.network = my_route->gateway;
+        rt.plen    = 32;
+        rt.gateway = 0;
+        _add_route(self, NULL, &rt, NULL);
+        /* adding the route might have invalidated the iteration. Start again. */
+        goto again;
+    }
 
-	NM_SET_OUT (out_ip4_dev_route_blacklist, ip4_dev_route_blacklist);
+    NM_SET_OUT(out_ip4_dev_route_blacklist, ip4_dev_route_blacklist);
 }
 
 gboolean
-nm_ip4_config_commit (const NMIP4Config *self,
-                      NMPlatform *platform,
-                      NMIPRouteTableSyncMode route_table_sync)
+nm_ip4_config_commit(const NMIP4Config *    self,
+                     NMPlatform *           platform,
+                     NMIPRouteTableSyncMode route_table_sync)
 {
-	gs_unref_ptrarray GPtrArray *addresses = NULL;
-	gs_unref_ptrarray GPtrArray *routes = NULL;
-	gs_unref_ptrarray GPtrArray *routes_prune = NULL;
-	int ifindex;
-	gboolean success = TRUE;
+    gs_unref_ptrarray GPtrArray *addresses    = NULL;
+    gs_unref_ptrarray GPtrArray *routes       = NULL;
+    gs_unref_ptrarray GPtrArray *routes_prune = NULL;
+    int                          ifindex;
+    gboolean                     success = TRUE;
 
-	g_return_val_if_fail (NM_IS_IP4_CONFIG (self), FALSE);
+    g_return_val_if_fail(NM_IS_IP4_CONFIG(self), FALSE);
 
-	ifindex = nm_ip4_config_get_ifindex (self);
-	g_return_val_if_fail (ifindex > 0, FALSE);
+    ifindex = nm_ip4_config_get_ifindex(self);
+    g_return_val_if_fail(ifindex > 0, FALSE);
 
-	addresses = nm_dedup_multi_objs_to_ptr_array_head (nm_ip4_config_lookup_addresses (self),
-	                                                   NULL, NULL);
+    addresses =
+        nm_dedup_multi_objs_to_ptr_array_head(nm_ip4_config_lookup_addresses(self), NULL, NULL);
 
-	routes = nm_dedup_multi_objs_to_ptr_array_head (nm_ip4_config_lookup_routes (self),
-	                                                NULL, NULL);
+    routes = nm_dedup_multi_objs_to_ptr_array_head(nm_ip4_config_lookup_routes(self), NULL, NULL);
 
-	routes_prune = nm_platform_ip_route_get_prune_list (platform,
-	                                                    AF_INET,
-	                                                    ifindex,
-	                                                    route_table_sync);
+    routes_prune =
+        nm_platform_ip_route_get_prune_list(platform, AF_INET, ifindex, route_table_sync);
 
-	nm_platform_ip4_address_sync (platform, ifindex, addresses);
+    nm_platform_ip4_address_sync(platform, ifindex, addresses);
 
-	if (!nm_platform_ip_route_sync (platform,
-	                                AF_INET,
-	                                ifindex,
-	                                routes,
-	                                routes_prune,
-	                                NULL))
-		success = FALSE;
+    if (!nm_platform_ip_route_sync(platform, AF_INET, ifindex, routes, routes_prune, NULL))
+        success = FALSE;
 
-	return success;
+    return success;
 }
 
 void
-_nm_ip_config_merge_route_attributes (int addr_family,
-                                      NMIPRoute *s_route,
-                                      NMPlatformIPRoute *r,
-                                      guint32 route_table)
-{
-	GVariant *variant;
-	guint32 table;
-	NMIPAddr addr;
-	NMPlatformIP4Route *r4 = (NMPlatformIP4Route *) r;
-	NMPlatformIP6Route *r6 = (NMPlatformIP6Route *) r;
-	gboolean onlink;
-
-	nm_assert (s_route);
-	nm_assert_addr_family (addr_family);
-	nm_assert (r);
-
-#define GET_ATTR(name, dst, variant_type, type, dflt) \
-	G_STMT_START { \
-		GVariant *_variant = nm_ip_route_get_attribute (s_route, ""name""); \
-		\
-		if (   _variant \
-		    && g_variant_is_of_type (_variant, G_VARIANT_TYPE_ ## variant_type)) \
-			(dst) = g_variant_get_ ## type (_variant); \
-		else \
-			(dst) = (dflt); \
-	} G_STMT_END
-
-	if (   (variant = nm_ip_route_get_attribute (s_route, NM_IP_ROUTE_ATTRIBUTE_TYPE))
-	    && g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING)) {
-		guint8 type;
-
-		type = nm_utils_route_type_by_name (g_variant_get_string (variant, NULL));
-		nm_assert (NM_IN_SET (type,
-		                      RTN_UNICAST,
-		                      RTN_LOCAL));
-
-		r->type_coerced = nm_platform_route_type_coerce (type);
-	} else
-		r->type_coerced = nm_platform_route_type_coerce (RTN_UNICAST);
-
-	GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_TABLE, table, UINT32, uint32, 0);
-
-	if (   !table
-	    && r->type_coerced == nm_platform_route_type_coerce (RTN_LOCAL))
-		r->table_coerced = nm_platform_route_table_coerce (RT_TABLE_LOCAL);
-	else
-		r->table_coerced = nm_platform_route_table_coerce (table ?: (route_table ?: RT_TABLE_MAIN));
-
-	if (addr_family == AF_INET) {
-		guint8 scope;
-
-		GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_TOS,        r4->tos,           BYTE,     byte, 0);
-		GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_SCOPE,      scope,             BYTE,     byte, RT_SCOPE_NOWHERE);
-		r4->scope_inv = nm_platform_route_scope_inv (scope);
-	}
-
-	GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_ONLINK,         onlink,            BOOLEAN,  boolean, FALSE);
-
-	r->r_rtm_flags = ((onlink) ? (unsigned) RTNH_F_ONLINK : 0u);
-
-	GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_WINDOW,         r->window,         UINT32,   uint32, 0);
-	GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_CWND,           r->cwnd,           UINT32,   uint32, 0);
-	GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_INITCWND,       r->initcwnd,       UINT32,   uint32, 0);
-	GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_INITRWND,       r->initrwnd,       UINT32,   uint32, 0);
-	GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_MTU,            r->mtu,            UINT32,   uint32, 0);
-	GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_WINDOW,    r->lock_window,    BOOLEAN,  boolean, FALSE);
-	GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_CWND,      r->lock_cwnd,      BOOLEAN,  boolean, FALSE);
-	GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_INITCWND,  r->lock_initcwnd,  BOOLEAN,  boolean, FALSE);
-	GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_INITRWND,  r->lock_initrwnd,  BOOLEAN,  boolean, FALSE);
-	GET_ATTR (NM_IP_ROUTE_ATTRIBUTE_LOCK_MTU,       r->lock_mtu,       BOOLEAN,  boolean, FALSE);
-
-	if (   (variant = nm_ip_route_get_attribute (s_route, NM_IP_ROUTE_ATTRIBUTE_SRC))
-	    && g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING)) {
-		if (inet_pton (addr_family, g_variant_get_string (variant, NULL), &addr) == 1) {
-			if (addr_family == AF_INET)
-				r4->pref_src = addr.addr4;
-			else
-				r6->pref_src = addr.addr6;
-		}
-	}
-
-	if (   addr_family == AF_INET6
-	    && (variant = nm_ip_route_get_attribute (s_route, NM_IP_ROUTE_ATTRIBUTE_FROM))
-	    && g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING)) {
-		gs_free char *string = NULL;
-		guint8 plen = 128;
-		char *sep;
-
-		string = g_variant_dup_string (variant, NULL);
-		sep = strchr (string, '/');
-		if (sep) {
-			*sep = 0;
-			plen = _nm_utils_ascii_str_to_int64 (sep + 1, 10, 1, 128, 255);
-		}
-		if (   plen <= 128
-		    && inet_pton (AF_INET6, string, &addr) == 1) {
-			r6->src = addr.addr6;
-			r6->src_plen = plen;
-		}
-	}
-#undef GET_ATTR
-}
-
-void
-nm_ip4_config_merge_setting (NMIP4Config *self,
-                             NMSettingIPConfig *setting,
-                             NMSettingConnectionMdns mdns,
-                             NMSettingConnectionLlmnr llmnr,
-                             guint32 route_table,
-                             guint32 route_metric)
-{
-	guint naddresses, nroutes, nnameservers, nsearches;
-	int i, priority;
-	const char *gateway_str;
-	guint32 gateway_bin;
-
-	if (!setting)
-		return;
-
-	g_return_if_fail (NM_IS_SETTING_IP4_CONFIG (setting));
-
-	g_object_freeze_notify (G_OBJECT (self));
-
-	naddresses = nm_setting_ip_config_get_num_addresses (setting);
-	nroutes = nm_setting_ip_config_get_num_routes (setting);
-	nnameservers = nm_setting_ip_config_get_num_dns (setting);
-	nsearches = nm_setting_ip_config_get_num_dns_searches (setting);
-
-	/* Gateway */
-	if (   !nm_setting_ip_config_get_never_default (setting)
-	    && (gateway_str = nm_setting_ip_config_get_gateway (setting))
-	    && inet_pton (AF_INET, gateway_str, &gateway_bin) == 1
-	    && gateway_bin) {
-		const NMPlatformIP4Route r = {
-			.rt_source = NM_IP_CONFIG_SOURCE_USER,
-			.gateway = gateway_bin,
-			.table_coerced = nm_platform_route_table_coerce (route_table),
-			.metric = route_metric,
-		};
-
-		_add_route (self, NULL, &r, NULL);
-	}
-
-	/* Addresses */
-	for (i = 0; i < naddresses; i++) {
-		NMIPAddress *s_addr = nm_setting_ip_config_get_address (setting, i);
-		GVariant *label;
-		NMPlatformIP4Address address;
-
-		memset (&address, 0, sizeof (address));
-		nm_ip_address_get_address_binary (s_addr, &address.address);
-		address.peer_address = address.address;
-		address.plen = nm_ip_address_get_prefix (s_addr);
-		nm_assert (address.plen <= 32);
-		address.lifetime = NM_PLATFORM_LIFETIME_PERMANENT;
-		address.preferred = NM_PLATFORM_LIFETIME_PERMANENT;
-		address.addr_source = NM_IP_CONFIG_SOURCE_USER;
-
-		label = nm_ip_address_get_attribute (s_addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL);
-		if (label)
-			g_strlcpy (address.label, g_variant_get_string (label, NULL), sizeof (address.label));
-
-		_add_address (self, NULL, &address);
-	}
-
-	/* Routes */
-	for (i = 0; i < nroutes; i++) {
-		NMIPRoute *s_route = nm_setting_ip_config_get_route (setting, i);
-		NMPlatformIP4Route route;
-		gint64 m;
-
-		if (nm_ip_route_get_family (s_route) != AF_INET) {
-			nm_assert_not_reached ();
-			continue;
-		}
-
-		memset (&route, 0, sizeof (route));
-		nm_ip_route_get_dest_binary (s_route, &route.network);
-
-		route.plen = nm_ip_route_get_prefix (s_route);
-		nm_assert (route.plen <= 32);
-
-		nm_ip_route_get_next_hop_binary (s_route, &route.gateway);
-		m = nm_ip_route_get_metric (s_route);
-		if (m < 0)
-			route.metric = route_metric;
-		else
-			route.metric = m;
-		route.rt_source = NM_IP_CONFIG_SOURCE_USER;
-
-		route.network = nm_utils_ip4_address_clear_host_address (route.network, route.plen);
-
-		_nm_ip_config_merge_route_attributes (AF_INET,
-		                                      s_route,
-		                                      NM_PLATFORM_IP_ROUTE_CAST (&route),
-		                                      route_table);
-		_add_route (self, NULL, &route, NULL);
-	}
-
-	/* DNS */
-	if (nm_setting_ip_config_get_ignore_auto_dns (setting)) {
-		nm_ip4_config_reset_nameservers (self);
-		nm_ip4_config_reset_domains (self);
-		nm_ip4_config_reset_searches (self);
-	}
-	for (i = 0; i < nnameservers; i++) {
-		guint32 ip;
-
-		if (inet_pton (AF_INET, nm_setting_ip_config_get_dns (setting, i), &ip) == 1)
-			nm_ip4_config_add_nameserver (self, ip);
-	}
-	for (i = 0; i < nsearches; i++)
-		nm_ip4_config_add_search (self, 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_ip4_config_add_dns_option (self, nm_setting_ip_config_get_dns_option (setting, i));
-		i++;
-	}
-
-	priority = nm_setting_ip_config_get_dns_priority (setting);
-	if (priority)
-		nm_ip4_config_set_dns_priority (self, priority);
-
-	nm_ip4_config_mdns_set (self, mdns);
-	nm_ip4_config_llmnr_set (self, llmnr);
-
-	g_object_thaw_notify (G_OBJECT (self));
+nm_ip4_config_merge_setting(NMIP4Config *            self,
+                            NMSettingIPConfig *      setting,
+                            NMSettingConnectionMdns  mdns,
+                            NMSettingConnectionLlmnr llmnr,
+                            guint32                  route_table,
+                            guint32                  route_metric)
+{
+    guint       naddresses, nroutes, nnameservers, nsearches;
+    int         i, priority;
+    const char *gateway_str;
+    guint32     gateway_bin;
+
+    if (!setting)
+        return;
+
+    g_return_if_fail(NM_IS_SETTING_IP4_CONFIG(setting));
+
+    g_object_freeze_notify(G_OBJECT(self));
+
+    naddresses   = nm_setting_ip_config_get_num_addresses(setting);
+    nroutes      = nm_setting_ip_config_get_num_routes(setting);
+    nnameservers = nm_setting_ip_config_get_num_dns(setting);
+    nsearches    = nm_setting_ip_config_get_num_dns_searches(setting);
+
+    /* Gateway */
+    if (!nm_setting_ip_config_get_never_default(setting)
+        && (gateway_str = nm_setting_ip_config_get_gateway(setting))
+        && inet_pton(AF_INET, gateway_str, &gateway_bin) == 1 && gateway_bin) {
+        const NMPlatformIP4Route r = {
+            .rt_source     = NM_IP_CONFIG_SOURCE_USER,
+            .gateway       = gateway_bin,
+            .table_coerced = nm_platform_route_table_coerce(route_table),
+            .metric        = route_metric,
+        };
+
+        _add_route(self, NULL, &r, NULL);
+    }
+
+    /* Addresses */
+    for (i = 0; i < naddresses; i++) {
+        NMIPAddress *        s_addr = nm_setting_ip_config_get_address(setting, i);
+        GVariant *           label;
+        NMPlatformIP4Address address;
+
+        memset(&address, 0, sizeof(address));
+        nm_ip_address_get_address_binary(s_addr, &address.address);
+        address.peer_address = address.address;
+        address.plen         = nm_ip_address_get_prefix(s_addr);
+        nm_assert(address.plen <= 32);
+        address.lifetime    = NM_PLATFORM_LIFETIME_PERMANENT;
+        address.preferred   = NM_PLATFORM_LIFETIME_PERMANENT;
+        address.addr_source = NM_IP_CONFIG_SOURCE_USER;
+
+        label = nm_ip_address_get_attribute(s_addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL);
+        if (label)
+            g_strlcpy(address.label, g_variant_get_string(label, NULL), sizeof(address.label));
+
+        _add_address(self, NULL, &address);
+    }
+
+    /* Routes */
+    for (i = 0; i < nroutes; i++) {
+        NMIPRoute *        s_route = nm_setting_ip_config_get_route(setting, i);
+        NMPlatformIP4Route route;
+        gint64             m;
+
+        if (nm_ip_route_get_family(s_route) != AF_INET) {
+            nm_assert_not_reached();
+            continue;
+        }
+
+        memset(&route, 0, sizeof(route));
+        nm_ip_route_get_dest_binary(s_route, &route.network);
+
+        route.plen = nm_ip_route_get_prefix(s_route);
+        nm_assert(route.plen <= 32);
+
+        nm_ip_route_get_next_hop_binary(s_route, &route.gateway);
+        m = nm_ip_route_get_metric(s_route);
+        if (m < 0)
+            route.metric = route_metric;
+        else
+            route.metric = m;
+        route.rt_source = NM_IP_CONFIG_SOURCE_USER;
+
+        route.network = nm_utils_ip4_address_clear_host_address(route.network, route.plen);
+
+        nm_utils_ip_route_attribute_to_platform(AF_INET,
+                                                s_route,
+                                                NM_PLATFORM_IP_ROUTE_CAST(&route),
+                                                route_table);
+        _add_route(self, NULL, &route, NULL);
+    }
+
+    /* DNS */
+    if (nm_setting_ip_config_get_ignore_auto_dns(setting)) {
+        nm_ip4_config_reset_nameservers(self);
+        nm_ip4_config_reset_domains(self);
+        nm_ip4_config_reset_searches(self);
+    }
+    for (i = 0; i < nnameservers; i++) {
+        guint32 ip;
+
+        if (inet_pton(AF_INET, nm_setting_ip_config_get_dns(setting, i), &ip) == 1)
+            nm_ip4_config_add_nameserver(self, ip);
+    }
+    for (i = 0; i < nsearches; i++)
+        nm_ip4_config_add_search(self, 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_ip4_config_add_dns_option(self, nm_setting_ip_config_get_dns_option(setting, i));
+        i++;
+    }
+
+    priority = nm_setting_ip_config_get_dns_priority(setting);
+    if (priority)
+        nm_ip4_config_set_dns_priority(self, priority);
+
+    nm_ip4_config_mdns_set(self, mdns);
+    nm_ip4_config_llmnr_set(self, llmnr);
+
+    g_object_thaw_notify(G_OBJECT(self));
 }
 
 NMSetting *
-nm_ip4_config_create_setting (const NMIP4Config *self)
-{
-	const NMIP4ConfigPrivate *priv;
-	NMSettingIPConfig *s_ip4;
-	guint nnameservers, nsearches, noptions;
-	const char *method = NULL;
-	int i;
-	NMDedupMultiIter ipconf_iter;
-	const NMPlatformIP4Address *address;
-	const NMPlatformIP4Route *route;
-	char sbuf[NM_UTILS_INET_ADDRSTRLEN];
-
-	s_ip4 = NM_SETTING_IP_CONFIG (nm_setting_ip4_config_new ());
-
-	if (!self) {
-		g_object_set (s_ip4,
-		              NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_DISABLED,
-		              NULL);
-		return NM_SETTING (s_ip4);
-	}
-
-	priv = NM_IP4_CONFIG_GET_PRIVATE (self);
-
-	nnameservers = nm_ip4_config_get_num_nameservers (self);
-	nsearches = nm_ip4_config_get_num_searches (self);
-	noptions = nm_ip4_config_get_num_dns_options (self);
-
-	/* Addresses */
-	nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, self, &address) {
-		NMIPAddress *s_addr;
-
-		/* Detect dynamic address */
-		if (address->lifetime != NM_PLATFORM_LIFETIME_PERMANENT) {
-			method = NM_SETTING_IP4_CONFIG_METHOD_AUTO;
-			continue;
-		}
-
-		/* Static address found. */
-		if (!method)
-			method = NM_SETTING_IP4_CONFIG_METHOD_MANUAL;
-
-		s_addr = nm_ip_address_new_binary (AF_INET, &address->address, address->plen, NULL);
-		if (*address->label)
-			nm_ip_address_set_attribute (s_addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL, g_variant_new_string (address->label));
-
-		nm_setting_ip_config_add_address (s_ip4, s_addr);
-		nm_ip_address_unref (s_addr);
-	}
-
-	/* Gateway */
-	if (   priv->best_default_route
-	    && nm_setting_ip_config_get_num_addresses (s_ip4) > 0) {
-		g_object_set (s_ip4,
-		              NM_SETTING_IP_CONFIG_GATEWAY,
-		              _nm_utils_inet4_ntop (NMP_OBJECT_CAST_IP4_ROUTE (priv->best_default_route)->gateway,
-		                                    sbuf),
-		              NULL);
-	}
-
-	/* Use 'disabled' if the method wasn't previously set */
-	if (!method)
-		method = NM_SETTING_IP4_CONFIG_METHOD_DISABLED;
-
-	g_object_set (s_ip4,
-	              NM_SETTING_IP_CONFIG_METHOD, method,
-	              NULL);
-
-	/* Routes */
-	nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, self, &route) {
-		NMIPRoute *s_route;
-
-		if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route))
-			continue;
-
-		/* Ignore routes provided by external sources */
-		if (route->rt_source != nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER))
-			continue;
-
-		s_route = nm_ip_route_new_binary (AF_INET,
-		                                  &route->network,
-		                                  route->plen,
-		                                  &route->gateway,
-		                                  route->metric,
-		                                  NULL);
-		nm_setting_ip_config_add_route (s_ip4, s_route);
-		nm_ip_route_unref (s_route);
-	}
-
-	/* DNS */
-	for (i = 0; i < nnameservers; i++) {
-		guint32 nameserver = nm_ip4_config_get_nameserver (self, i);
-
-		nm_setting_ip_config_add_dns (s_ip4, _nm_utils_inet4_ntop (nameserver, sbuf));
-	}
-	for (i = 0; i < nsearches; i++) {
-		const char *search = nm_ip4_config_get_search (self, i);
-
-		nm_setting_ip_config_add_dns_search (s_ip4, search);
-	}
-
-	for (i = 0; i < noptions; i++) {
-		const char *option = nm_ip4_config_get_dns_option (self, i);
-
-		nm_setting_ip_config_add_dns_option (s_ip4, option);
-	}
-
-	g_object_set (s_ip4,
-	              NM_SETTING_IP_CONFIG_DNS_PRIORITY,
-	              nm_ip4_config_get_dns_priority (self),
-	              NULL);
-
-	return NM_SETTING (s_ip4);
+nm_ip4_config_create_setting(const NMIP4Config *self)
+{
+    const NMIP4ConfigPrivate *  priv;
+    NMSettingIPConfig *         s_ip4;
+    guint                       nnameservers, nsearches, noptions;
+    const char *                method = NULL;
+    int                         i;
+    NMDedupMultiIter            ipconf_iter;
+    const NMPlatformIP4Address *address;
+    const NMPlatformIP4Route *  route;
+    char                        sbuf[NM_UTILS_INET_ADDRSTRLEN];
+
+    s_ip4 = NM_SETTING_IP_CONFIG(nm_setting_ip4_config_new());
+
+    if (!self) {
+        g_object_set(s_ip4,
+                     NM_SETTING_IP_CONFIG_METHOD,
+                     NM_SETTING_IP4_CONFIG_METHOD_DISABLED,
+                     NULL);
+        return NM_SETTING(s_ip4);
+    }
+
+    priv = NM_IP4_CONFIG_GET_PRIVATE(self);
+
+    nnameservers = nm_ip4_config_get_num_nameservers(self);
+    nsearches    = nm_ip4_config_get_num_searches(self);
+    noptions     = nm_ip4_config_get_num_dns_options(self);
+
+    /* Addresses */
+    nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, self, &address) {
+        NMIPAddress *s_addr;
+
+        /* Detect dynamic address */
+        if (address->lifetime != NM_PLATFORM_LIFETIME_PERMANENT) {
+            method = NM_SETTING_IP4_CONFIG_METHOD_AUTO;
+            continue;
+        }
+
+        /* Static address found. */
+        if (!method)
+            method = NM_SETTING_IP4_CONFIG_METHOD_MANUAL;
+
+        s_addr = nm_ip_address_new_binary(AF_INET, &address->address, address->plen, NULL);
+        if (*address->label)
+            nm_ip_address_set_attribute(s_addr,
+                                        NM_IP_ADDRESS_ATTRIBUTE_LABEL,
+                                        g_variant_new_string(address->label));
+
+        nm_setting_ip_config_add_address(s_ip4, s_addr);
+        nm_ip_address_unref(s_addr);
+    }
+
+    /* Gateway */
+    if (priv->best_default_route && nm_setting_ip_config_get_num_addresses(s_ip4) > 0) {
+        g_object_set(
+            s_ip4,
+            NM_SETTING_IP_CONFIG_GATEWAY,
+            _nm_utils_inet4_ntop(NMP_OBJECT_CAST_IP4_ROUTE(priv->best_default_route)->gateway,
+                                 sbuf),
+            NULL);
+    }
+
+    /* Use 'disabled' if the method wasn't previously set */
+    if (!method)
+        method = NM_SETTING_IP4_CONFIG_METHOD_DISABLED;
+
+    g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, method, NULL);
+
+    /* Routes */
+    nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, self, &route) {
+        NMIPRoute *s_route;
+
+        if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT(route))
+            continue;
+
+        /* Ignore routes provided by external sources */
+        if (route->rt_source
+            != nmp_utils_ip_config_source_round_trip_rtprot(NM_IP_CONFIG_SOURCE_USER))
+            continue;
+
+        s_route = nm_ip_route_new_binary(AF_INET,
+                                         &route->network,
+                                         route->plen,
+                                         &route->gateway,
+                                         route->metric,
+                                         NULL);
+        nm_setting_ip_config_add_route(s_ip4, s_route);
+        nm_ip_route_unref(s_route);
+    }
+
+    /* DNS */
+    for (i = 0; i < nnameservers; i++) {
+        guint32 nameserver = nm_ip4_config_get_nameserver(self, i);
+
+        nm_setting_ip_config_add_dns(s_ip4, _nm_utils_inet4_ntop(nameserver, sbuf));
+    }
+    for (i = 0; i < nsearches; i++) {
+        const char *search = nm_ip4_config_get_search(self, i);
+
+        nm_setting_ip_config_add_dns_search(s_ip4, search);
+    }
+
+    for (i = 0; i < noptions; i++) {
+        const char *option = nm_ip4_config_get_dns_option(self, i);
+
+        nm_setting_ip_config_add_dns_option(s_ip4, option);
+    }
+
+    g_object_set(s_ip4,
+                 NM_SETTING_IP_CONFIG_DNS_PRIORITY,
+                 nm_ip4_config_get_dns_priority(self),
+                 NULL);
+
+    return NM_SETTING(s_ip4);
 }
 
 /*****************************************************************************/
 
 void
-nm_ip4_config_merge (NMIP4Config *dst,
-                     const NMIP4Config *src,
-                     NMIPConfigMergeFlags merge_flags,
-                     guint32 default_route_metric_penalty)
-{
-	NMIP4ConfigPrivate *dst_priv;
-	const NMIP4ConfigPrivate *src_priv;
-	guint32 i;
-	NMDedupMultiIter ipconf_iter;
-	const NMPlatformIP4Address *address = NULL;
-
-	g_return_if_fail (src != NULL);
-	g_return_if_fail (dst != NULL);
-
-	dst_priv = NM_IP4_CONFIG_GET_PRIVATE (dst);
-	src_priv = NM_IP4_CONFIG_GET_PRIVATE (src);
-
-	g_object_freeze_notify (G_OBJECT (dst));
-
-	/* addresses */
-	nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, src, &address) {
-		if (   NM_FLAGS_HAS (merge_flags, NM_IP_CONFIG_MERGE_EXTERNAL)
-		    && !address->external) {
-			NMPlatformIP4Address a;
-
-			a = *address;
-			a.external = TRUE;
-			_add_address (dst, NULL, &a);
-		} else
-			_add_address (dst, NMP_OBJECT_UP_CAST (address), NULL);
-	}
-
-	/* nameservers */
-	if (!NM_FLAGS_HAS (merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) {
-		for (i = 0; i < nm_ip4_config_get_num_nameservers (src); i++)
-			nm_ip4_config_add_nameserver (dst, nm_ip4_config_get_nameserver (src, i));
-	}
-
-	/* routes */
-	if (!NM_FLAGS_HAS (merge_flags, NM_IP_CONFIG_MERGE_NO_ROUTES)) {
-		const NMPlatformIP4Route *r_src;
-
-		nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, src, &r_src) {
-			if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (r_src)) {
-				if (   NM_FLAGS_HAS (merge_flags, NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES)
-				    && !NM_FLAGS_HAS (src_priv->config_flags, NM_IP_CONFIG_FLAGS_IGNORE_MERGE_NO_DEFAULT_ROUTES))
-					continue;
-				if (default_route_metric_penalty) {
-					NMPlatformIP4Route r = *r_src;
-
-					r.metric = nm_utils_ip_route_metric_penalize (r.metric, default_route_metric_penalty);
-					_add_route (dst, NULL, &r, NULL);
-					continue;
-				}
-			}
-			_add_route (dst, ipconf_iter.current->obj, NULL, NULL);
-		}
-	}
-
-	/* domains */
-	if (!NM_FLAGS_HAS (merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) {
-		for (i = 0; i < nm_ip4_config_get_num_domains (src); i++)
-			nm_ip4_config_add_domain (dst, nm_ip4_config_get_domain (src, i));
-	}
-
-	/* dns searches */
-	if (!NM_FLAGS_HAS (merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) {
-		for (i = 0; i < nm_ip4_config_get_num_searches (src); i++)
-			nm_ip4_config_add_search (dst, nm_ip4_config_get_search (src, i));
-	}
-
-	/* dns options */
-	if (!NM_FLAGS_HAS (merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) {
-		for (i = 0; i < nm_ip4_config_get_num_dns_options (src); i++)
-			nm_ip4_config_add_dns_option (dst, nm_ip4_config_get_dns_option (src, i));
-	}
-
-	/* MTU */
-	if (   src_priv->mtu_source > dst_priv->mtu_source
-	    || (   src_priv->mtu_source == dst_priv->mtu_source
-	        && (   (!dst_priv->mtu && src_priv->mtu)
-	            || (dst_priv->mtu && src_priv->mtu < dst_priv->mtu))))
-		nm_ip4_config_set_mtu (dst, src_priv->mtu, src_priv->mtu_source);
-
-	/* NIS */
-	if (!NM_FLAGS_HAS (merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) {
-		for (i = 0; i < nm_ip4_config_get_num_nis_servers (src); i++)
-			nm_ip4_config_add_nis_server (dst, nm_ip4_config_get_nis_server (src, i));
-
-		if (nm_ip4_config_get_nis_domain (src))
-			nm_ip4_config_set_nis_domain (dst, nm_ip4_config_get_nis_domain (src));
-	}
-
-	/* WINS */
-	if (!NM_FLAGS_HAS (merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) {
-		for (i = 0; i < nm_ip4_config_get_num_wins (src); i++)
-			nm_ip4_config_add_wins (dst, nm_ip4_config_get_wins (src, i));
-	}
-
-	/* metered flag */
-	nm_ip4_config_set_metered (dst, nm_ip4_config_get_metered (dst) ||
-	                                nm_ip4_config_get_metered (src));
-
-	/* DNS priority */
-	if (nm_ip4_config_get_dns_priority (src))
-		nm_ip4_config_set_dns_priority (dst, nm_ip4_config_get_dns_priority (src));
-
-	/* mdns */
-	nm_ip4_config_mdns_set (dst,
-	                        NM_MAX (nm_ip4_config_mdns_get (src),
-	                                nm_ip4_config_mdns_get (dst)));
-	/* LLMNR */
-	nm_ip4_config_llmnr_set (dst,
-	                         NM_MAX (nm_ip4_config_llmnr_get (src),
-	                                 nm_ip4_config_llmnr_get (dst)));
-
-	g_object_thaw_notify (G_OBJECT (dst));
+nm_ip4_config_merge(NMIP4Config *        dst,
+                    const NMIP4Config *  src,
+                    NMIPConfigMergeFlags merge_flags,
+                    guint32              default_route_metric_penalty)
+{
+    NMIP4ConfigPrivate *        dst_priv;
+    const NMIP4ConfigPrivate *  src_priv;
+    guint32                     i;
+    NMDedupMultiIter            ipconf_iter;
+    const NMPlatformIP4Address *address = NULL;
+
+    g_return_if_fail(src != NULL);
+    g_return_if_fail(dst != NULL);
+
+    dst_priv = NM_IP4_CONFIG_GET_PRIVATE(dst);
+    src_priv = NM_IP4_CONFIG_GET_PRIVATE(src);
+
+    g_object_freeze_notify(G_OBJECT(dst));
+
+    /* addresses */
+    nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, src, &address) {
+        if (NM_FLAGS_HAS(merge_flags, NM_IP_CONFIG_MERGE_EXTERNAL) && !address->external) {
+            NMPlatformIP4Address a;
+
+            a          = *address;
+            a.external = TRUE;
+            _add_address(dst, NULL, &a);
+        } else
+            _add_address(dst, NMP_OBJECT_UP_CAST(address), NULL);
+    }
+
+    /* nameservers */
+    if (!NM_FLAGS_HAS(merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) {
+        for (i = 0; i < nm_ip4_config_get_num_nameservers(src); i++)
+            nm_ip4_config_add_nameserver(dst, nm_ip4_config_get_nameserver(src, i));
+    }
+
+    /* routes */
+    if (!NM_FLAGS_HAS(merge_flags, NM_IP_CONFIG_MERGE_NO_ROUTES)) {
+        const NMPlatformIP4Route *r_src;
+
+        nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, src, &r_src) {
+            if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT(r_src)) {
+                if (NM_FLAGS_HAS(merge_flags, NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES)
+                    && !NM_FLAGS_HAS(src_priv->config_flags,
+                                     NM_IP_CONFIG_FLAGS_IGNORE_MERGE_NO_DEFAULT_ROUTES))
+                    continue;
+                if (default_route_metric_penalty) {
+                    NMPlatformIP4Route r = *r_src;
+
+                    r.metric =
+                        nm_utils_ip_route_metric_penalize(r.metric, default_route_metric_penalty);
+                    _add_route(dst, NULL, &r, NULL);
+                    continue;
+                }
+            }
+            _add_route(dst, ipconf_iter.current->obj, NULL, NULL);
+        }
+    }
+
+    /* domains */
+    if (!NM_FLAGS_HAS(merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) {
+        for (i = 0; i < nm_ip4_config_get_num_domains(src); i++)
+            nm_ip4_config_add_domain(dst, nm_ip4_config_get_domain(src, i));
+    }
+
+    /* dns searches */
+    if (!NM_FLAGS_HAS(merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) {
+        for (i = 0; i < nm_ip4_config_get_num_searches(src); i++)
+            nm_ip4_config_add_search(dst, nm_ip4_config_get_search(src, i));
+    }
+
+    /* dns options */
+    if (!NM_FLAGS_HAS(merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) {
+        for (i = 0; i < nm_ip4_config_get_num_dns_options(src); i++)
+            nm_ip4_config_add_dns_option(dst, nm_ip4_config_get_dns_option(src, i));
+    }
+
+    /* MTU */
+    if (src_priv->mtu_source > dst_priv->mtu_source
+        || (src_priv->mtu_source == dst_priv->mtu_source
+            && ((!dst_priv->mtu && src_priv->mtu)
+                || (dst_priv->mtu && src_priv->mtu < dst_priv->mtu))))
+        nm_ip4_config_set_mtu(dst, src_priv->mtu, src_priv->mtu_source);
+
+    /* NIS */
+    if (!NM_FLAGS_HAS(merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) {
+        for (i = 0; i < nm_ip4_config_get_num_nis_servers(src); i++)
+            nm_ip4_config_add_nis_server(dst, nm_ip4_config_get_nis_server(src, i));
+
+        if (nm_ip4_config_get_nis_domain(src))
+            nm_ip4_config_set_nis_domain(dst, nm_ip4_config_get_nis_domain(src));
+    }
+
+    /* WINS */
+    if (!NM_FLAGS_HAS(merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) {
+        for (i = 0; i < nm_ip4_config_get_num_wins(src); i++)
+            nm_ip4_config_add_wins(dst, nm_ip4_config_get_wins(src, i));
+    }
+
+    /* metered flag */
+    nm_ip4_config_set_metered(dst,
+                              nm_ip4_config_get_metered(dst) || nm_ip4_config_get_metered(src));
+
+    /* DNS priority */
+    if (nm_ip4_config_get_dns_priority(src))
+        nm_ip4_config_set_dns_priority(dst, nm_ip4_config_get_dns_priority(src));
+
+    /* mdns */
+    nm_ip4_config_mdns_set(dst, NM_MAX(nm_ip4_config_mdns_get(src), nm_ip4_config_mdns_get(dst)));
+    /* LLMNR */
+    nm_ip4_config_llmnr_set(dst,
+                            NM_MAX(nm_ip4_config_llmnr_get(src), nm_ip4_config_llmnr_get(dst)));
+
+    g_object_thaw_notify(G_OBJECT(dst));
 }
 
 /*****************************************************************************/
 
 static int
-_nameservers_get_index (const NMIP4Config *self, guint32 ns)
+_nameservers_get_index(const NMIP4Config *self, guint32 ns)
 {
-	const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
-	guint i;
+    const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
+    guint                     i;
 
-	for (i = 0; i < priv->nameservers->len; i++) {
-		guint32 n = g_array_index (priv->nameservers, guint32, i);
+    for (i = 0; i < priv->nameservers->len; i++) {
+        guint32 n = g_array_index(priv->nameservers, guint32, i);
 
-		if (ns == n)
-			return (int) i;
-	}
-	return -1;
+        if (ns == n)
+            return (int) i;
+    }
+    return -1;
 }
 
 static int
-_domains_get_index (const NMIP4Config *self, const char *domain)
+_domains_get_index(const NMIP4Config *self, const char *domain)
 {
-	const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
-	guint i;
+    const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
+    guint                     i;
 
-	for (i = 0; i < priv->domains->len; i++) {
-		const char *d = g_ptr_array_index (priv->domains, i);
+    for (i = 0; i < priv->domains->len; i++) {
+        const char *d = g_ptr_array_index(priv->domains, i);
 
-		if (g_strcmp0 (domain, d) == 0)
-			return (int) i;
-	}
-	return -1;
+        if (g_strcmp0(domain, d) == 0)
+            return (int) i;
+    }
+    return -1;
 }
 
 static int
-_searches_get_index (const NMIP4Config *self, const char *search)
+_searches_get_index(const NMIP4Config *self, const char *search)
 {
-	const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
-	guint i;
+    const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
+    guint                     i;
 
-	for (i = 0; i < priv->searches->len; i++) {
-		const char *s = g_ptr_array_index (priv->searches, i);
+    for (i = 0; i < priv->searches->len; i++) {
+        const char *s = g_ptr_array_index(priv->searches, i);
 
-		if (g_strcmp0 (search, s) == 0)
-			return (int) i;
-	}
-	return -1;
+        if (g_strcmp0(search, s) == 0)
+            return (int) i;
+    }
+    return -1;
 }
 
 static int
-_dns_options_get_index (const NMIP4Config *self, const char *option)
+_dns_options_get_index(const NMIP4Config *self, const char *option)
 {
-	const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
-	guint i;
+    const NMIP4ConfigPrivate *priv = NM_IP4_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);
+    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;
+        if (g_strcmp0(option, s) == 0)
+            return (int) i;
+    }
+    return -1;
 }
 
 static int
-_nis_servers_get_index (const NMIP4Config *self, guint32 nis_server)
+_nis_servers_get_index(const NMIP4Config *self, guint32 nis_server)
 {
-	const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
-	guint i;
+    const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
+    guint                     i;
 
-	for (i = 0; i < priv->nis->len; i++) {
-		guint32 n = g_array_index (priv->nis, guint32, i);
+    for (i = 0; i < priv->nis->len; i++) {
+        guint32 n = g_array_index(priv->nis, guint32, i);
 
-		if (n == nis_server)
-			return (int) i;
-	}
-	return -1;
+        if (n == nis_server)
+            return (int) i;
+    }
+    return -1;
 }
 
 static int
-_wins_get_index (const NMIP4Config *self, guint32 wins_server)
+_wins_get_index(const NMIP4Config *self, guint32 wins_server)
 {
-	const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
-	guint i;
+    const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
+    guint                     i;
 
-	for (i = 0; i < priv->wins->len; i++) {
-		guint32 n = g_array_index (priv->wins, guint32, i);
+    for (i = 0; i < priv->wins->len; i++) {
+        guint32 n = g_array_index(priv->wins, guint32, i);
 
-		if (n == wins_server)
-			return (int) i;
-	}
-	return -1;
+        if (n == wins_server)
+            return (int) i;
+    }
+    return -1;
 }
 
 /*****************************************************************************/
@@ -1432,255 +1241,254 @@ _wins_get_index (const NMIP4Config *self, guint32 wins_server)
  * Removes everything in @src from @dst.
  */
 void
-nm_ip4_config_subtract (NMIP4Config *dst,
-                        const NMIP4Config *src,
-                        guint32 default_route_metric_penalty)
-{
-	NMIP4ConfigPrivate *dst_priv;
-	guint i;
-	int idx;
-	const NMPlatformIP4Address *a;
-	const NMPlatformIP4Route *r;
-	NMDedupMultiIter ipconf_iter;
-	gboolean changed;
-	gboolean changed_default_route;
-
-	g_return_if_fail (src != NULL);
-	g_return_if_fail (dst != NULL);
-
-	dst_priv = NM_IP4_CONFIG_GET_PRIVATE (dst);
-
-	g_object_freeze_notify (G_OBJECT (dst));
-
-	/* addresses */
-	changed = FALSE;
-	nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, src, &a) {
-		if (nm_dedup_multi_index_remove_obj (dst_priv->multi_idx,
-		                                     &dst_priv->idx_ip4_addresses,
-		                                     NMP_OBJECT_UP_CAST (a),
-		                                     NULL))
-			changed = TRUE;
-	}
-	if (changed)
-		_notify_addresses (dst);
-
-	/* nameservers */
-	for (i = 0; i < nm_ip4_config_get_num_nameservers (src); i++) {
-		idx = _nameservers_get_index (dst, nm_ip4_config_get_nameserver (src, i));
-		if (idx >= 0)
-			nm_ip4_config_del_nameserver (dst, idx);
-	}
-
-	/* routes */
-	changed = FALSE;
-	changed_default_route = FALSE;
-	nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, src, &r) {
-		const NMPObject *o_src = NMP_OBJECT_UP_CAST (r);
-		NMPObject o_lookup_copy;
-		const NMPObject *o_lookup;
-		nm_auto_nmpobj const NMPObject *obj_old = NULL;
-
-		if (   NM_PLATFORM_IP_ROUTE_IS_DEFAULT (r)
-		    && default_route_metric_penalty) {
-			NMPlatformIP4Route *rr;
-
-			/* the default route was penalized when merging it to the combined ip-config.
-			 * When subtracting the routes, we must re-do that process when comparing
-			 * the routes. */
-			o_lookup = nmp_object_stackinit_obj (&o_lookup_copy, o_src);
-			rr = NMP_OBJECT_CAST_IP4_ROUTE (&o_lookup_copy);
-			rr->metric = nm_utils_ip_route_metric_penalize (rr->metric, default_route_metric_penalty);
-		} else
-			o_lookup = o_src;
-
-		if (nm_dedup_multi_index_remove_obj (dst_priv->multi_idx,
-		                                     &dst_priv->idx_ip4_routes,
-		                                     o_lookup,
-		                                     (gconstpointer *) &obj_old)) {
-			if (dst_priv->best_default_route == obj_old) {
-				nm_clear_nmp_object (&dst_priv->best_default_route);
-				changed_default_route = TRUE;
-			}
-			changed = TRUE;
-		}
-	}
-	if (changed_default_route) {
-		_nm_ip_config_best_default_route_set (&dst_priv->best_default_route,
-		                                      _nm_ip4_config_best_default_route_find (dst));
-		_notify (dst, PROP_GATEWAY);
-	}
-	if (changed)
-		_notify_routes (dst);
-
-	/* domains */
-	for (i = 0; i < nm_ip4_config_get_num_domains (src); i++) {
-		idx = _domains_get_index (dst, nm_ip4_config_get_domain (src, i));
-		if (idx >= 0)
-			nm_ip4_config_del_domain (dst, idx);
-	}
-
-	/* dns searches */
-	for (i = 0; i < nm_ip4_config_get_num_searches (src); i++) {
-		idx = _searches_get_index (dst, nm_ip4_config_get_search (src, i));
-		if (idx >= 0)
-			nm_ip4_config_del_search (dst, idx);
-	}
-
-	/* dns options */
-	for (i = 0; i < nm_ip4_config_get_num_dns_options (src); i++) {
-		idx = _dns_options_get_index (dst, nm_ip4_config_get_dns_option (src, i));
-		if (idx >= 0)
-			nm_ip4_config_del_dns_option (dst, idx);
-	}
-
-	/* MTU */
-	if (   nm_ip4_config_get_mtu (src) == nm_ip4_config_get_mtu (dst)
-	    && nm_ip4_config_get_mtu_source (src) == nm_ip4_config_get_mtu_source (dst))
-		nm_ip4_config_set_mtu (dst, 0, NM_IP_CONFIG_SOURCE_UNKNOWN);
-
-	/* NIS */
-	for (i = 0; i < nm_ip4_config_get_num_nis_servers (src); i++) {
-		idx = _nis_servers_get_index (dst, nm_ip4_config_get_nis_server (src, i));
-		if (idx >= 0)
-			nm_ip4_config_del_nis_server (dst, idx);
-	}
-
-	if (g_strcmp0 (nm_ip4_config_get_nis_domain (src), nm_ip4_config_get_nis_domain (dst)) == 0)
-		nm_ip4_config_set_nis_domain (dst, NULL);
-
-	/* WINS */
-	for (i = 0; i < nm_ip4_config_get_num_wins (src); i++) {
-		idx = _wins_get_index (dst, nm_ip4_config_get_wins (src, i));
-		if (idx >= 0)
-			nm_ip4_config_del_wins (dst, idx);
-	}
-
-	/* DNS priority */
-	if (nm_ip4_config_get_dns_priority (src) == nm_ip4_config_get_dns_priority (dst))
-		nm_ip4_config_set_dns_priority (dst, 0);
-
-	/* mdns */
-	if (nm_ip4_config_mdns_get (src) == nm_ip4_config_mdns_get (dst))
-		nm_ip4_config_mdns_set (dst, NM_SETTING_CONNECTION_MDNS_DEFAULT);
-
-	/* LLMNR */
-	if (nm_ip4_config_llmnr_get (src) == nm_ip4_config_llmnr_get (dst))
-		nm_ip4_config_llmnr_set (dst, NM_SETTING_CONNECTION_LLMNR_DEFAULT);
-
-	g_object_thaw_notify (G_OBJECT (dst));
+nm_ip4_config_subtract(NMIP4Config *      dst,
+                       const NMIP4Config *src,
+                       guint32            default_route_metric_penalty)
+{
+    NMIP4ConfigPrivate *        dst_priv;
+    guint                       i;
+    int                         idx;
+    const NMPlatformIP4Address *a;
+    const NMPlatformIP4Route *  r;
+    NMDedupMultiIter            ipconf_iter;
+    gboolean                    changed;
+    gboolean                    changed_default_route;
+
+    g_return_if_fail(src != NULL);
+    g_return_if_fail(dst != NULL);
+
+    dst_priv = NM_IP4_CONFIG_GET_PRIVATE(dst);
+
+    g_object_freeze_notify(G_OBJECT(dst));
+
+    /* addresses */
+    changed = FALSE;
+    nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, src, &a) {
+        if (nm_dedup_multi_index_remove_obj(dst_priv->multi_idx,
+                                            &dst_priv->idx_ip4_addresses,
+                                            NMP_OBJECT_UP_CAST(a),
+                                            NULL))
+            changed = TRUE;
+    }
+    if (changed)
+        _notify_addresses(dst);
+
+    /* nameservers */
+    for (i = 0; i < nm_ip4_config_get_num_nameservers(src); i++) {
+        idx = _nameservers_get_index(dst, nm_ip4_config_get_nameserver(src, i));
+        if (idx >= 0)
+            nm_ip4_config_del_nameserver(dst, idx);
+    }
+
+    /* routes */
+    changed               = FALSE;
+    changed_default_route = FALSE;
+    nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, src, &r) {
+        const NMPObject *    o_src = NMP_OBJECT_UP_CAST(r);
+        NMPObject            o_lookup_copy;
+        const NMPObject *    o_lookup;
+        nm_auto_nmpobj const NMPObject *obj_old = NULL;
+
+        if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT(r) && default_route_metric_penalty) {
+            NMPlatformIP4Route *rr;
+
+            /* the default route was penalized when merging it to the combined ip-config.
+             * When subtracting the routes, we must re-do that process when comparing
+             * the routes. */
+            o_lookup = nmp_object_stackinit_obj(&o_lookup_copy, o_src);
+            rr       = NMP_OBJECT_CAST_IP4_ROUTE(&o_lookup_copy);
+            rr->metric =
+                nm_utils_ip_route_metric_penalize(rr->metric, default_route_metric_penalty);
+        } else
+            o_lookup = o_src;
+
+        if (nm_dedup_multi_index_remove_obj(dst_priv->multi_idx,
+                                            &dst_priv->idx_ip4_routes,
+                                            o_lookup,
+                                            (gconstpointer *) &obj_old)) {
+            if (dst_priv->best_default_route == obj_old) {
+                nm_clear_nmp_object(&dst_priv->best_default_route);
+                changed_default_route = TRUE;
+            }
+            changed = TRUE;
+        }
+    }
+    if (changed_default_route) {
+        nmp_object_ref_set(&dst_priv->best_default_route,
+                           _nm_ip4_config_best_default_route_find(dst));
+        _notify(dst, PROP_GATEWAY);
+    }
+    if (changed)
+        _notify_routes(dst);
+
+    /* domains */
+    for (i = 0; i < nm_ip4_config_get_num_domains(src); i++) {
+        idx = _domains_get_index(dst, nm_ip4_config_get_domain(src, i));
+        if (idx >= 0)
+            nm_ip4_config_del_domain(dst, idx);
+    }
+
+    /* dns searches */
+    for (i = 0; i < nm_ip4_config_get_num_searches(src); i++) {
+        idx = _searches_get_index(dst, nm_ip4_config_get_search(src, i));
+        if (idx >= 0)
+            nm_ip4_config_del_search(dst, idx);
+    }
+
+    /* dns options */
+    for (i = 0; i < nm_ip4_config_get_num_dns_options(src); i++) {
+        idx = _dns_options_get_index(dst, nm_ip4_config_get_dns_option(src, i));
+        if (idx >= 0)
+            nm_ip4_config_del_dns_option(dst, idx);
+    }
+
+    /* MTU */
+    if (nm_ip4_config_get_mtu(src) == nm_ip4_config_get_mtu(dst)
+        && nm_ip4_config_get_mtu_source(src) == nm_ip4_config_get_mtu_source(dst))
+        nm_ip4_config_set_mtu(dst, 0, NM_IP_CONFIG_SOURCE_UNKNOWN);
+
+    /* NIS */
+    for (i = 0; i < nm_ip4_config_get_num_nis_servers(src); i++) {
+        idx = _nis_servers_get_index(dst, nm_ip4_config_get_nis_server(src, i));
+        if (idx >= 0)
+            nm_ip4_config_del_nis_server(dst, idx);
+    }
+
+    if (g_strcmp0(nm_ip4_config_get_nis_domain(src), nm_ip4_config_get_nis_domain(dst)) == 0)
+        nm_ip4_config_set_nis_domain(dst, NULL);
+
+    /* WINS */
+    for (i = 0; i < nm_ip4_config_get_num_wins(src); i++) {
+        idx = _wins_get_index(dst, nm_ip4_config_get_wins(src, i));
+        if (idx >= 0)
+            nm_ip4_config_del_wins(dst, idx);
+    }
+
+    /* DNS priority */
+    if (nm_ip4_config_get_dns_priority(src) == nm_ip4_config_get_dns_priority(dst))
+        nm_ip4_config_set_dns_priority(dst, 0);
+
+    /* mdns */
+    if (nm_ip4_config_mdns_get(src) == nm_ip4_config_mdns_get(dst))
+        nm_ip4_config_mdns_set(dst, NM_SETTING_CONNECTION_MDNS_DEFAULT);
+
+    /* LLMNR */
+    if (nm_ip4_config_llmnr_get(src) == nm_ip4_config_llmnr_get(dst))
+        nm_ip4_config_llmnr_set(dst, NM_SETTING_CONNECTION_LLMNR_DEFAULT);
+
+    g_object_thaw_notify(G_OBJECT(dst));
 }
 
 static gboolean
-_nm_ip4_config_intersect_helper (NMIP4Config *dst,
-                                 const NMIP4Config *src,
-                                 gboolean intersect_addresses,
-                                 gboolean intersect_routes,
-                                 guint32 default_route_metric_penalty,
-                                 gboolean update_dst)
-{
-	NMIP4ConfigPrivate *dst_priv;
-	const NMIP4ConfigPrivate *src_priv;
-	NMDedupMultiIter ipconf_iter;
-	const NMPlatformIP4Address *a;
-	const NMPlatformIP4Route *r;
-	const NMPObject *new_best_default_route;
-	gboolean changed, result = FALSE;
-
-	g_return_val_if_fail (src, FALSE);
-	g_return_val_if_fail (dst, FALSE);
-
-	dst_priv = NM_IP4_CONFIG_GET_PRIVATE (dst);
-	src_priv = NM_IP4_CONFIG_GET_PRIVATE (src);
-
-	if (update_dst)
-		g_object_freeze_notify (G_OBJECT (dst));
-
-	/* addresses */
-	if (intersect_addresses) {
-		changed = FALSE;
-		nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, dst, &a) {
-			if (nm_dedup_multi_index_lookup_obj (src_priv->multi_idx,
-			                                     &src_priv->idx_ip4_addresses,
-			                                     NMP_OBJECT_UP_CAST (a)))
-				continue;
-
-			if (!update_dst)
-				return TRUE;
-
-			if (nm_dedup_multi_index_remove_entry (dst_priv->multi_idx,
-			                                       ipconf_iter.current) != 1)
-				nm_assert_not_reached ();
-			changed = TRUE;
-		}
-		if (changed) {
-			_notify_addresses (dst);
-			result = TRUE;
-		}
-	}
-
-	/* ignore nameservers */
-
-	/* routes */
-	if (!intersect_routes)
-		goto skip_routes;
-
-	changed = FALSE;
-	new_best_default_route = NULL;
-	nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, dst, &r) {
-		const NMPObject *o_dst = NMP_OBJECT_UP_CAST (r);
-		const NMPObject *o_lookup;
-		NMPObject o_lookup_copy;
-
-		if (   NM_PLATFORM_IP_ROUTE_IS_DEFAULT (r)
-		    && default_route_metric_penalty) {
-			NMPlatformIP4Route *rr;
-
-			/* the default route was penalized when merging it to the combined ip-config.
-			 * When intersecting the routes, we must re-do that process when comparing
-			 * the routes. */
-			o_lookup = nmp_object_stackinit_obj (&o_lookup_copy, o_dst);
-			rr = NMP_OBJECT_CAST_IP4_ROUTE (&o_lookup_copy);
-			rr->metric = nm_utils_ip_route_metric_penalize (rr->metric, default_route_metric_penalty);
-		} else
-			o_lookup = o_dst;
-
-		if (nm_dedup_multi_index_lookup_obj (src_priv->multi_idx,
-		                                     &src_priv->idx_ip4_routes,
-		                                     o_lookup)) {
-			new_best_default_route = _nm_ip_config_best_default_route_find_better (new_best_default_route, o_dst);
-			continue;
-		}
-
-		if (!update_dst)
-			return TRUE;
-
-		if (nm_dedup_multi_index_remove_entry (dst_priv->multi_idx,
-		                                       ipconf_iter.current) != 1)
-			nm_assert_not_reached ();
-		changed = TRUE;
-	}
-	if (_nm_ip_config_best_default_route_set (&dst_priv->best_default_route, new_best_default_route)) {
-		nm_assert (changed);
-		_notify (dst, PROP_GATEWAY);
-	}
-
-	if (changed) {
-		_notify_routes (dst);
-		result = TRUE;
-	}
+_nm_ip4_config_intersect_helper(NMIP4Config *      dst,
+                                const NMIP4Config *src,
+                                gboolean           intersect_addresses,
+                                gboolean           intersect_routes,
+                                guint32            default_route_metric_penalty,
+                                gboolean           update_dst)
+{
+    NMIP4ConfigPrivate *        dst_priv;
+    const NMIP4ConfigPrivate *  src_priv;
+    NMDedupMultiIter            ipconf_iter;
+    const NMPlatformIP4Address *a;
+    const NMPlatformIP4Route *  r;
+    const NMPObject *           new_best_default_route;
+    gboolean                    changed, result = FALSE;
+
+    g_return_val_if_fail(src, FALSE);
+    g_return_val_if_fail(dst, FALSE);
+
+    dst_priv = NM_IP4_CONFIG_GET_PRIVATE(dst);
+    src_priv = NM_IP4_CONFIG_GET_PRIVATE(src);
+
+    if (update_dst)
+        g_object_freeze_notify(G_OBJECT(dst));
+
+    /* addresses */
+    if (intersect_addresses) {
+        changed = FALSE;
+        nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, dst, &a) {
+            if (nm_dedup_multi_index_lookup_obj(src_priv->multi_idx,
+                                                &src_priv->idx_ip4_addresses,
+                                                NMP_OBJECT_UP_CAST(a)))
+                continue;
+
+            if (!update_dst)
+                return TRUE;
+
+            if (nm_dedup_multi_index_remove_entry(dst_priv->multi_idx, ipconf_iter.current) != 1)
+                nm_assert_not_reached();
+            changed = TRUE;
+        }
+        if (changed) {
+            _notify_addresses(dst);
+            result = TRUE;
+        }
+    }
+
+    /* ignore nameservers */
+
+    /* routes */
+    if (!intersect_routes)
+        goto skip_routes;
+
+    changed                = FALSE;
+    new_best_default_route = NULL;
+    nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, dst, &r) {
+        const NMPObject *o_dst = NMP_OBJECT_UP_CAST(r);
+        const NMPObject *o_lookup;
+        NMPObject        o_lookup_copy;
+
+        if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT(r) && default_route_metric_penalty) {
+            NMPlatformIP4Route *rr;
+
+            /* the default route was penalized when merging it to the combined ip-config.
+             * When intersecting the routes, we must re-do that process when comparing
+             * the routes. */
+            o_lookup = nmp_object_stackinit_obj(&o_lookup_copy, o_dst);
+            rr       = NMP_OBJECT_CAST_IP4_ROUTE(&o_lookup_copy);
+            rr->metric =
+                nm_utils_ip_route_metric_penalize(rr->metric, default_route_metric_penalty);
+        } else
+            o_lookup = o_dst;
+
+        if (nm_dedup_multi_index_lookup_obj(src_priv->multi_idx,
+                                            &src_priv->idx_ip4_routes,
+                                            o_lookup)) {
+            new_best_default_route =
+                _nm_ip_config_best_default_route_find_better(new_best_default_route, o_dst);
+            continue;
+        }
+
+        if (!update_dst)
+            return TRUE;
+
+        if (nm_dedup_multi_index_remove_entry(dst_priv->multi_idx, ipconf_iter.current) != 1)
+            nm_assert_not_reached();
+        changed = TRUE;
+    }
+    if (nmp_object_ref_set(&dst_priv->best_default_route, new_best_default_route)) {
+        nm_assert(changed);
+        _notify(dst, PROP_GATEWAY);
+    }
+
+    if (changed) {
+        _notify_routes(dst);
+        result = TRUE;
+    }
 
 skip_routes:
-	/* ignore domains */
-	/* ignore dns searches */
-	/* ignore dns options */
-	/* ignore NIS */
-	/* ignore WINS */
-	/* ignore mdns */
-	/* ignore LLMNR */
+    /* ignore domains */
+    /* ignore dns searches */
+    /* ignore dns options */
+    /* ignore NIS */
+    /* ignore WINS */
+    /* ignore mdns */
+    /* ignore LLMNR */
 
-	if (update_dst)
-		g_object_thaw_notify (G_OBJECT (dst));
-	return result;
+    if (update_dst)
+        g_object_thaw_notify(G_OBJECT(dst));
+    return result;
 }
 
 /**
@@ -1695,18 +1503,18 @@ skip_routes:
  * with the result.
  */
 void
-nm_ip4_config_intersect (NMIP4Config *dst,
-                         const NMIP4Config *src,
-                         gboolean intersect_addresses,
-                         gboolean intersect_routes,
-                         guint32 default_route_metric_penalty)
+nm_ip4_config_intersect(NMIP4Config *      dst,
+                        const NMIP4Config *src,
+                        gboolean           intersect_addresses,
+                        gboolean           intersect_routes,
+                        guint32            default_route_metric_penalty)
 {
-	_nm_ip4_config_intersect_helper (dst,
-	                                 src,
-	                                 intersect_addresses,
-	                                 intersect_routes,
-	                                 default_route_metric_penalty,
-	                                 TRUE);
+    _nm_ip4_config_intersect_helper(dst,
+                                    src,
+                                    intersect_addresses,
+                                    intersect_routes,
+                                    default_route_metric_penalty,
+                                    TRUE);
 }
 
 /**
@@ -1727,29 +1535,30 @@ nm_ip4_config_intersect (NMIP4Config *dst,
  * to @a and @b.
  */
 NMIP4Config *
-nm_ip4_config_intersect_alloc (const NMIP4Config *a,
-                               const NMIP4Config *b,
-                               gboolean intersect_addresses,
-                               gboolean intersect_routes,
-                               guint32 default_route_metric_penalty)
-{
-	NMIP4Config *a_copy;
-
-	if (_nm_ip4_config_intersect_helper ((NMIP4Config *) a, b,
-	                                     intersect_addresses,
-	                                     intersect_routes,
-	                                     default_route_metric_penalty,
-	                                     FALSE)) {
-		a_copy = nm_ip4_config_clone (a);
-		_nm_ip4_config_intersect_helper (a_copy,
-		                                 b,
-		                                 intersect_addresses,
-		                                 intersect_routes,
-		                                 default_route_metric_penalty,
-		                                 TRUE);
-		return a_copy;
-	} else
-		return NULL;
+nm_ip4_config_intersect_alloc(const NMIP4Config *a,
+                              const NMIP4Config *b,
+                              gboolean           intersect_addresses,
+                              gboolean           intersect_routes,
+                              guint32            default_route_metric_penalty)
+{
+    NMIP4Config *a_copy;
+
+    if (_nm_ip4_config_intersect_helper((NMIP4Config *) a,
+                                        b,
+                                        intersect_addresses,
+                                        intersect_routes,
+                                        default_route_metric_penalty,
+                                        FALSE)) {
+        a_copy = nm_ip4_config_clone(a);
+        _nm_ip4_config_intersect_helper(a_copy,
+                                        b,
+                                        intersect_addresses,
+                                        intersect_routes,
+                                        default_route_metric_penalty,
+                                        TRUE);
+        return a_copy;
+    } else
+        return NULL;
 }
 
 /**
@@ -1767,416 +1576,430 @@ nm_ip4_config_intersect_alloc (const NMIP4Config *a,
  * that are not signaled by the output parameter @relevant_changes).
  */
 gboolean
-nm_ip4_config_replace (NMIP4Config *dst, const NMIP4Config *src, gboolean *relevant_changes)
+nm_ip4_config_replace(NMIP4Config *dst, const NMIP4Config *src, gboolean *relevant_changes)
 {
 #if NM_MORE_ASSERTS
-	gboolean config_equal;
+    gboolean config_equal;
 #endif
-	gboolean has_minor_changes = FALSE, has_relevant_changes = FALSE, are_equal;
-	guint i, num;
-	NMIP4ConfigPrivate *dst_priv;
-	const NMIP4ConfigPrivate *src_priv;
-	NMDedupMultiIter ipconf_iter_src, ipconf_iter_dst;
-	const NMDedupMultiHeadEntry *head_entry_src;
-	const NMPObject *new_best_default_route;
-
-	g_return_val_if_fail (src != NULL, FALSE);
-	g_return_val_if_fail (dst != NULL, FALSE);
-	g_return_val_if_fail (src != dst, FALSE);
+    gboolean                     has_minor_changes = FALSE, has_relevant_changes = FALSE, are_equal;
+    guint                        i, num;
+    NMIP4ConfigPrivate *         dst_priv;
+    const NMIP4ConfigPrivate *   src_priv;
+    NMDedupMultiIter             ipconf_iter_src, ipconf_iter_dst;
+    const NMDedupMultiHeadEntry *head_entry_src;
+    const NMPObject *            new_best_default_route;
+
+    g_return_val_if_fail(src != NULL, FALSE);
+    g_return_val_if_fail(dst != NULL, FALSE);
+    g_return_val_if_fail(src != dst, FALSE);
 
 #if NM_MORE_ASSERTS
-	config_equal = nm_ip4_config_equal (dst, src);
+    config_equal = nm_ip4_config_equal(dst, src);
 #endif
 
-	dst_priv = NM_IP4_CONFIG_GET_PRIVATE (dst);
-	src_priv = NM_IP4_CONFIG_GET_PRIVATE (src);
-
-	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;
-	}
-
-	/* addresses */
-	head_entry_src = nm_ip4_config_lookup_addresses (src);
-	nm_dedup_multi_iter_init (&ipconf_iter_src, head_entry_src);
-	nm_ip_config_iter_ip4_address_init (&ipconf_iter_dst, dst);
-	are_equal = TRUE;
-	while (TRUE) {
-		gboolean has;
-		const NMPlatformIP4Address *r_src = NULL;
-		const NMPlatformIP4Address *r_dst = NULL;
-
-		has = nm_ip_config_iter_ip4_address_next (&ipconf_iter_src, &r_src);
-		if (has != nm_ip_config_iter_ip4_address_next (&ipconf_iter_dst, &r_dst)) {
-			are_equal = FALSE;
-			has_relevant_changes = TRUE;
-			break;
-		}
-		if (!has)
-			break;
-
-		if (nm_platform_ip4_address_cmp (r_src, r_dst) != 0) {
-			are_equal = FALSE;
-			if (   r_src->address != r_dst->address
-			    || r_src->plen != r_dst->plen
-			    || r_src->peer_address != r_dst->peer_address) {
-				has_relevant_changes = TRUE;
-				break;
-			}
-		}
-	}
-	if (!are_equal) {
-		has_minor_changes = TRUE;
-		nm_dedup_multi_index_dirty_set_idx (dst_priv->multi_idx, &dst_priv->idx_ip4_addresses);
-		nm_dedup_multi_iter_for_each (&ipconf_iter_src, head_entry_src) {
-			_nm_ip_config_add_obj (dst_priv->multi_idx,
-			                       &dst_priv->idx_ip4_addresses_,
-			                       dst_priv->ifindex,
-			                       ipconf_iter_src.current->obj,
-			                       NULL,
-			                       FALSE,
-			                       TRUE,
-			                       NULL,
-			                       NULL);
-		}
-		nm_dedup_multi_index_dirty_remove_idx (dst_priv->multi_idx, &dst_priv->idx_ip4_addresses, FALSE);
-		_notify_addresses (dst);
-	}
-
-	/* routes */
-	head_entry_src = nm_ip4_config_lookup_routes (src);
-	nm_dedup_multi_iter_init (&ipconf_iter_src, head_entry_src);
-	nm_ip_config_iter_ip4_route_init (&ipconf_iter_dst, dst);
-	are_equal = TRUE;
-	while (TRUE) {
-		gboolean has;
-		const NMPlatformIP4Route *r_src = NULL;
-		const NMPlatformIP4Route *r_dst = NULL;
-
-		has = nm_ip_config_iter_ip4_route_next (&ipconf_iter_src, &r_src);
-		if (has != nm_ip_config_iter_ip4_route_next (&ipconf_iter_dst, &r_dst)) {
-			are_equal = FALSE;
-			has_relevant_changes = TRUE;
-			break;
-		}
-		if (!has)
-			break;
-
-		if (nm_platform_ip4_route_cmp_full (r_src, r_dst) != 0) {
-			are_equal = FALSE;
-			if (   r_src->plen != r_dst->plen
-			    || !nm_utils_ip4_address_same_prefix (r_src->network, r_dst->network, r_src->plen)
-			    || r_src->gateway != r_dst->gateway
-			    || r_src->metric != r_dst->metric) {
-				has_relevant_changes = TRUE;
-				break;
-			}
-		}
-	}
-	if (!are_equal) {
-		has_minor_changes = TRUE;
-		new_best_default_route = NULL;
-		nm_dedup_multi_index_dirty_set_idx (dst_priv->multi_idx, &dst_priv->idx_ip4_routes);
-		nm_dedup_multi_iter_for_each (&ipconf_iter_src, head_entry_src) {
-			const NMPObject *o = ipconf_iter_src.current->obj;
-			const NMPObject *obj_new;
-
-			_nm_ip_config_add_obj (dst_priv->multi_idx,
-			                       &dst_priv->idx_ip4_routes_,
-			                       dst_priv->ifindex,
-			                       o,
-			                       NULL,
-			                       FALSE,
-			                       TRUE,
-			                       NULL,
-			                       &obj_new);
-			new_best_default_route = _nm_ip_config_best_default_route_find_better (new_best_default_route, obj_new);
-		}
-		nm_dedup_multi_index_dirty_remove_idx (dst_priv->multi_idx, &dst_priv->idx_ip4_routes, FALSE);
-		if (_nm_ip_config_best_default_route_set (&dst_priv->best_default_route, new_best_default_route))
-			_notify (dst, PROP_GATEWAY);
-		_notify_routes (dst);
-	}
-
-	/* nameservers */
-	num = nm_ip4_config_get_num_nameservers (src);
-	are_equal = num == nm_ip4_config_get_num_nameservers (dst);
-	if (are_equal) {
-		for (i = 0; i < num; i++ ) {
-			if (nm_ip4_config_get_nameserver (src, i) != nm_ip4_config_get_nameserver (dst, i)) {
-				are_equal = FALSE;
-				break;
-			}
-		}
-	}
-	if (!are_equal) {
-		nm_ip4_config_reset_nameservers (dst);
-		for (i = 0; i < num; i++)
-			nm_ip4_config_add_nameserver (dst, nm_ip4_config_get_nameserver (src, i));
-		has_relevant_changes = TRUE;
-	}
-
-	/* domains */
-	num = nm_ip4_config_get_num_domains (src);
-	are_equal = num == nm_ip4_config_get_num_domains (dst);
-	if (are_equal) {
-		for (i = 0; i < num; i++ ) {
-			if (g_strcmp0 (nm_ip4_config_get_domain (src, i),
-			               nm_ip4_config_get_domain (dst, i))) {
-				are_equal = FALSE;
-				break;
-			}
-		}
-	}
-	if (!are_equal) {
-		nm_ip4_config_reset_domains (dst);
-		for (i = 0; i < num; i++)
-			nm_ip4_config_add_domain (dst, nm_ip4_config_get_domain (src, i));
-		has_relevant_changes = TRUE;
-	}
-
-	/* dns searches */
-	num = nm_ip4_config_get_num_searches (src);
-	are_equal = num == nm_ip4_config_get_num_searches (dst);
-	if (are_equal) {
-		for (i = 0; i < num; i++ ) {
-			if (g_strcmp0 (nm_ip4_config_get_search (src, i),
-			               nm_ip4_config_get_search (dst, i))) {
-				are_equal = FALSE;
-				break;
-			}
-		}
-	}
-	if (!are_equal) {
-		nm_ip4_config_reset_searches (dst);
-		for (i = 0; i < num; i++)
-			nm_ip4_config_add_search (dst, nm_ip4_config_get_search (src, i));
-		has_relevant_changes = TRUE;
-	}
-
-	/* dns options */
-	num = nm_ip4_config_get_num_dns_options (src);
-	are_equal = num == nm_ip4_config_get_num_dns_options (dst);
-	if (are_equal) {
-		for (i = 0; i < num; i++ ) {
-			if (g_strcmp0 (nm_ip4_config_get_dns_option (src, i),
-			               nm_ip4_config_get_dns_option (dst, i))) {
-				are_equal = FALSE;
-				break;
-			}
-		}
-	}
-	if (!are_equal) {
-		nm_ip4_config_reset_dns_options (dst);
-		for (i = 0; i < num; i++)
-			nm_ip4_config_add_dns_option (dst, nm_ip4_config_get_dns_option (src, i));
-		has_relevant_changes = TRUE;
-	}
-
-	if (src_priv->mdns != dst_priv->mdns) {
-		dst_priv->mdns = src_priv->mdns;
-		has_relevant_changes = TRUE;
-	}
-
-	if (src_priv->llmnr != dst_priv->llmnr) {
-		dst_priv->llmnr = src_priv->llmnr;
-		has_relevant_changes = TRUE;
-	}
-
-	/* DNS priority */
-	if (src_priv->dns_priority != dst_priv->dns_priority) {
-		nm_ip4_config_set_dns_priority (dst, src_priv->dns_priority);
-		has_minor_changes = TRUE;
-	}
-
-	/* nis */
-	num = nm_ip4_config_get_num_nis_servers (src);
-	are_equal = num == nm_ip4_config_get_num_nis_servers (dst);
-	if (are_equal) {
-		for (i = 0; i < num; i++ ) {
-			if (nm_ip4_config_get_nis_server (src, i) != nm_ip4_config_get_nis_server (dst, i)) {
-				are_equal = FALSE;
-				break;
-			}
-		}
-	}
-	if (!are_equal) {
-		nm_ip4_config_reset_nis_servers (dst);
-		for (i = 0; i < num; i++)
-			nm_ip4_config_add_nis_server (dst, nm_ip4_config_get_nis_server (src, i));
-		has_relevant_changes = TRUE;
-	}
-
-	/* nis_domain */
-	if (g_strcmp0 (src_priv->nis_domain, dst_priv->nis_domain)) {
-		nm_ip4_config_set_nis_domain (dst, src_priv->nis_domain);
-		has_relevant_changes = TRUE;
-	}
-
-	/* wins */
-	num = nm_ip4_config_get_num_wins (src);
-	are_equal = num == nm_ip4_config_get_num_wins (dst);
-	if (are_equal) {
-		for (i = 0; i < num; i++ ) {
-			if (nm_ip4_config_get_wins (src, i) != nm_ip4_config_get_wins (dst, i)) {
-				are_equal = FALSE;
-				break;
-			}
-		}
-	}
-	if (!are_equal) {
-		nm_ip4_config_reset_wins (dst);
-		for (i = 0; i < num; i++)
-			nm_ip4_config_add_wins (dst, nm_ip4_config_get_wins (src, i));
-		has_relevant_changes = TRUE;
-	}
-
-	/* mtu */
-	if (   src_priv->mtu != dst_priv->mtu
-	    || src_priv->mtu_source != dst_priv->mtu_source) {
-		nm_ip4_config_set_mtu (dst, src_priv->mtu, src_priv->mtu_source);
-		has_minor_changes = TRUE;
-	}
-
-	/* metered */
-	if (src_priv->metered != dst_priv->metered) {
-		dst_priv->metered = src_priv->metered;
-		has_minor_changes = TRUE;
-	}
+    dst_priv = NM_IP4_CONFIG_GET_PRIVATE(dst);
+    src_priv = NM_IP4_CONFIG_GET_PRIVATE(src);
+
+    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;
+    }
+
+    /* addresses */
+    head_entry_src = nm_ip4_config_lookup_addresses(src);
+    nm_dedup_multi_iter_init(&ipconf_iter_src, head_entry_src);
+    nm_ip_config_iter_ip4_address_init(&ipconf_iter_dst, dst);
+    are_equal = TRUE;
+    while (TRUE) {
+        gboolean                    has;
+        const NMPlatformIP4Address *r_src = NULL;
+        const NMPlatformIP4Address *r_dst = NULL;
+
+        has = nm_platform_dedup_multi_iter_next_ip4_address(&ipconf_iter_src, &r_src);
+        if (has != nm_platform_dedup_multi_iter_next_ip4_address(&ipconf_iter_dst, &r_dst)) {
+            are_equal            = FALSE;
+            has_relevant_changes = TRUE;
+            break;
+        }
+        if (!has)
+            break;
+
+        if (nm_platform_ip4_address_cmp(r_src, r_dst) != 0) {
+            are_equal = FALSE;
+            if (r_src->address != r_dst->address || r_src->plen != r_dst->plen
+                || r_src->peer_address != r_dst->peer_address) {
+                has_relevant_changes = TRUE;
+                break;
+            }
+        }
+    }
+    if (!are_equal) {
+        has_minor_changes = TRUE;
+        nm_dedup_multi_index_dirty_set_idx(dst_priv->multi_idx, &dst_priv->idx_ip4_addresses);
+        nm_dedup_multi_iter_for_each (&ipconf_iter_src, head_entry_src) {
+            _nm_ip_config_add_obj(dst_priv->multi_idx,
+                                  &dst_priv->idx_ip4_addresses_,
+                                  dst_priv->ifindex,
+                                  ipconf_iter_src.current->obj,
+                                  NULL,
+                                  FALSE,
+                                  TRUE,
+                                  NULL,
+                                  NULL);
+        }
+        nm_dedup_multi_index_dirty_remove_idx(dst_priv->multi_idx,
+                                              &dst_priv->idx_ip4_addresses,
+                                              FALSE);
+        _notify_addresses(dst);
+    }
+
+    /* routes */
+    head_entry_src = nm_ip4_config_lookup_routes(src);
+    nm_dedup_multi_iter_init(&ipconf_iter_src, head_entry_src);
+    nm_ip_config_iter_ip4_route_init(&ipconf_iter_dst, dst);
+    are_equal = TRUE;
+    while (TRUE) {
+        gboolean                  has;
+        const NMPlatformIP4Route *r_src = NULL;
+        const NMPlatformIP4Route *r_dst = NULL;
+
+        has = nm_platform_dedup_multi_iter_next_ip4_route(&ipconf_iter_src, &r_src);
+        if (has != nm_platform_dedup_multi_iter_next_ip4_route(&ipconf_iter_dst, &r_dst)) {
+            are_equal            = FALSE;
+            has_relevant_changes = TRUE;
+            break;
+        }
+        if (!has)
+            break;
+
+        if (nm_platform_ip4_route_cmp_full(r_src, r_dst) != 0) {
+            are_equal = FALSE;
+            if (r_src->plen != r_dst->plen
+                || !nm_utils_ip4_address_same_prefix(r_src->network, r_dst->network, r_src->plen)
+                || r_src->gateway != r_dst->gateway || r_src->metric != r_dst->metric) {
+                has_relevant_changes = TRUE;
+                break;
+            }
+        }
+    }
+    if (!are_equal) {
+        has_minor_changes      = TRUE;
+        new_best_default_route = NULL;
+        nm_dedup_multi_index_dirty_set_idx(dst_priv->multi_idx, &dst_priv->idx_ip4_routes);
+        nm_dedup_multi_iter_for_each (&ipconf_iter_src, head_entry_src) {
+            const NMPObject *o = ipconf_iter_src.current->obj;
+            const NMPObject *obj_new;
+
+            _nm_ip_config_add_obj(dst_priv->multi_idx,
+                                  &dst_priv->idx_ip4_routes_,
+                                  dst_priv->ifindex,
+                                  o,
+                                  NULL,
+                                  FALSE,
+                                  TRUE,
+                                  NULL,
+                                  &obj_new);
+            new_best_default_route =
+                _nm_ip_config_best_default_route_find_better(new_best_default_route, obj_new);
+        }
+        nm_dedup_multi_index_dirty_remove_idx(dst_priv->multi_idx,
+                                              &dst_priv->idx_ip4_routes,
+                                              FALSE);
+        if (nmp_object_ref_set(&dst_priv->best_default_route, new_best_default_route))
+            _notify(dst, PROP_GATEWAY);
+        _notify_routes(dst);
+    }
+
+    /* nameservers */
+    num       = nm_ip4_config_get_num_nameservers(src);
+    are_equal = num == nm_ip4_config_get_num_nameservers(dst);
+    if (are_equal) {
+        for (i = 0; i < num; i++) {
+            if (nm_ip4_config_get_nameserver(src, i) != nm_ip4_config_get_nameserver(dst, i)) {
+                are_equal = FALSE;
+                break;
+            }
+        }
+    }
+    if (!are_equal) {
+        nm_ip4_config_reset_nameservers(dst);
+        for (i = 0; i < num; i++)
+            nm_ip4_config_add_nameserver(dst, nm_ip4_config_get_nameserver(src, i));
+        has_relevant_changes = TRUE;
+    }
+
+    /* domains */
+    num       = nm_ip4_config_get_num_domains(src);
+    are_equal = num == nm_ip4_config_get_num_domains(dst);
+    if (are_equal) {
+        for (i = 0; i < num; i++) {
+            if (g_strcmp0(nm_ip4_config_get_domain(src, i), nm_ip4_config_get_domain(dst, i))) {
+                are_equal = FALSE;
+                break;
+            }
+        }
+    }
+    if (!are_equal) {
+        nm_ip4_config_reset_domains(dst);
+        for (i = 0; i < num; i++)
+            nm_ip4_config_add_domain(dst, nm_ip4_config_get_domain(src, i));
+        has_relevant_changes = TRUE;
+    }
+
+    /* dns searches */
+    num       = nm_ip4_config_get_num_searches(src);
+    are_equal = num == nm_ip4_config_get_num_searches(dst);
+    if (are_equal) {
+        for (i = 0; i < num; i++) {
+            if (g_strcmp0(nm_ip4_config_get_search(src, i), nm_ip4_config_get_search(dst, i))) {
+                are_equal = FALSE;
+                break;
+            }
+        }
+    }
+    if (!are_equal) {
+        nm_ip4_config_reset_searches(dst);
+        for (i = 0; i < num; i++)
+            nm_ip4_config_add_search(dst, nm_ip4_config_get_search(src, i));
+        has_relevant_changes = TRUE;
+    }
+
+    /* dns options */
+    num       = nm_ip4_config_get_num_dns_options(src);
+    are_equal = num == nm_ip4_config_get_num_dns_options(dst);
+    if (are_equal) {
+        for (i = 0; i < num; i++) {
+            if (g_strcmp0(nm_ip4_config_get_dns_option(src, i),
+                          nm_ip4_config_get_dns_option(dst, i))) {
+                are_equal = FALSE;
+                break;
+            }
+        }
+    }
+    if (!are_equal) {
+        nm_ip4_config_reset_dns_options(dst);
+        for (i = 0; i < num; i++)
+            nm_ip4_config_add_dns_option(dst, nm_ip4_config_get_dns_option(src, i));
+        has_relevant_changes = TRUE;
+    }
+
+    if (src_priv->mdns != dst_priv->mdns) {
+        dst_priv->mdns       = src_priv->mdns;
+        has_relevant_changes = TRUE;
+    }
+
+    if (src_priv->llmnr != dst_priv->llmnr) {
+        dst_priv->llmnr      = src_priv->llmnr;
+        has_relevant_changes = TRUE;
+    }
+
+    /* DNS priority */
+    if (src_priv->dns_priority != dst_priv->dns_priority) {
+        nm_ip4_config_set_dns_priority(dst, src_priv->dns_priority);
+        has_minor_changes = TRUE;
+    }
+
+    /* nis */
+    num       = nm_ip4_config_get_num_nis_servers(src);
+    are_equal = num == nm_ip4_config_get_num_nis_servers(dst);
+    if (are_equal) {
+        for (i = 0; i < num; i++) {
+            if (nm_ip4_config_get_nis_server(src, i) != nm_ip4_config_get_nis_server(dst, i)) {
+                are_equal = FALSE;
+                break;
+            }
+        }
+    }
+    if (!are_equal) {
+        nm_ip4_config_reset_nis_servers(dst);
+        for (i = 0; i < num; i++)
+            nm_ip4_config_add_nis_server(dst, nm_ip4_config_get_nis_server(src, i));
+        has_relevant_changes = TRUE;
+    }
+
+    /* nis_domain */
+    if (g_strcmp0(src_priv->nis_domain, dst_priv->nis_domain)) {
+        nm_ip4_config_set_nis_domain(dst, src_priv->nis_domain);
+        has_relevant_changes = TRUE;
+    }
+
+    /* wins */
+    num       = nm_ip4_config_get_num_wins(src);
+    are_equal = num == nm_ip4_config_get_num_wins(dst);
+    if (are_equal) {
+        for (i = 0; i < num; i++) {
+            if (nm_ip4_config_get_wins(src, i) != nm_ip4_config_get_wins(dst, i)) {
+                are_equal = FALSE;
+                break;
+            }
+        }
+    }
+    if (!are_equal) {
+        nm_ip4_config_reset_wins(dst);
+        for (i = 0; i < num; i++)
+            nm_ip4_config_add_wins(dst, nm_ip4_config_get_wins(src, i));
+        has_relevant_changes = TRUE;
+    }
+
+    /* mtu */
+    if (src_priv->mtu != dst_priv->mtu || src_priv->mtu_source != dst_priv->mtu_source) {
+        nm_ip4_config_set_mtu(dst, src_priv->mtu, src_priv->mtu_source);
+        has_minor_changes = TRUE;
+    }
+
+    /* metered */
+    if (src_priv->metered != dst_priv->metered) {
+        dst_priv->metered = src_priv->metered;
+        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. */
-	nm_assert (config_equal == !has_relevant_changes);
+    /* 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. */
+    nm_assert(config_equal == !has_relevant_changes);
 #endif
 
-	g_object_thaw_notify (G_OBJECT (dst));
+    g_object_thaw_notify(G_OBJECT(dst));
 
-	if (relevant_changes)
-		*relevant_changes = has_relevant_changes;
+    if (relevant_changes)
+        *relevant_changes = has_relevant_changes;
 
-	return has_relevant_changes || has_minor_changes;
+    return has_relevant_changes || has_minor_changes;
 }
 
 void
-nm_ip_config_dump (const NMIPConfig *self,
-                   const char *detail,
-                   NMLogLevel level,
-                   NMLogDomain domain)
-{
-	NMDedupMultiIter ipconf_iter;
-	const NMPlatformIP4Address *addr4;
-	const NMPlatformIP6Address *addr6;
-	const NMPlatformIP4Route *route4;
-	const NMPlatformIP6Route *route6;
-	const NMIP4Config *ip4;
-	const NMIP6Config *ip6;
-	int addr_family = AF_UNSPEC;
-	char addr_family_char = '?';
-	const char *path;
-	gconstpointer ptr;
-	guint i;
-
-	if (self) {
-		addr_family = nm_ip_config_get_addr_family (self);
-		addr_family_char = nm_utils_addr_family_to_char (addr_family);
-	}
-
-	nm_log (level, domain, NULL, NULL,
-	        "---- NMIP%cConfig %p (%s)",
-	        addr_family_char,
-	        self,
-	        detail);
-
-	if (!self)
-		return;
-
-	path = nm_dbus_object_get_path (NM_DBUS_OBJECT (self));
-	if (path)
-		nm_log (level, domain, NULL, NULL, " path     : %s", path);
-
-	if (addr_family == AF_INET) {
-		ip4 = NM_IP4_CONFIG (self);
-		nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, ip4, &addr4) {
-			nm_log (level, domain, NULL, NULL, " address  : %s",
-			        nm_platform_ip4_address_to_string (addr4, NULL, 0));
-		}
-		nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, ip4, &route4) {
-			nm_log (level, domain, NULL, NULL, " route    : %s",
-			        nm_platform_ip4_route_to_string (route4, NULL, 0));
-		}
-	} else {
-		ip6 = NM_IP6_CONFIG (self);
-		nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, ip6, &addr6) {
-			nm_log (level, domain, NULL, NULL, " address  : %s",
-			        nm_platform_ip6_address_to_string (addr6, NULL, 0));
-		}
-		nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, ip6, &route6) {
-			nm_log (level, domain, NULL, NULL, " route    : %s",
-			        nm_platform_ip6_route_to_string (route6, NULL, 0));
-		}
-	}
-
-	for (i = 0; i < nm_ip_config_get_num_nameservers (self); i++) {
-		char buf[NM_UTILS_INET_ADDRSTRLEN];
-
-		ptr = nm_ip_config_get_nameserver (self, i);
-		nm_log (level, domain, NULL, NULL, " dns      : %s",
-		        nm_utils_inet_ntop (addr_family, ptr, buf));
-	}
-
-	for (i = 0; i < nm_ip_config_get_num_domains (self); i++)
-		nm_log (level, domain, NULL, NULL, " domain   : %s", nm_ip_config_get_domain (self, i));
-
-	for (i = 0; i < nm_ip_config_get_num_searches (self); i++)
-		nm_log (level, domain, NULL, NULL, " search   : %s", nm_ip_config_get_search (self, i));
-
-	for (i = 0; i < nm_ip_config_get_num_dns_options (self); i++)
-		nm_log (level, domain, NULL, NULL, "dns-option: %s", nm_ip_config_get_dns_option (self, i));
-
-	nm_log (level, domain, NULL, NULL, " dns-prio : %d", nm_ip_config_get_dns_priority (self));
-
-	if (addr_family == AF_INET) {
-		ip4 = NM_IP4_CONFIG (self);
-		nm_log (level, domain, NULL, NULL,
-		        " mtu      : %"G_GUINT32_FORMAT" (source: %d)",
-		        nm_ip4_config_get_mtu (ip4),
-		        (int) nm_ip4_config_get_mtu_source (ip4));
-		nm_log (level, domain, NULL, NULL, " metered  : %d",
-		        (int) nm_ip4_config_get_metered (ip4));
-	}
+nm_ip_config_dump(const NMIPConfig *self, const char *detail, NMLogLevel level, NMLogDomain domain)
+{
+    NMDedupMultiIter            ipconf_iter;
+    const NMPlatformIP4Address *addr4;
+    const NMPlatformIP6Address *addr6;
+    const NMPlatformIP4Route *  route4;
+    const NMPlatformIP6Route *  route6;
+    const NMIP4Config *         ip4;
+    const NMIP6Config *         ip6;
+    int                         addr_family      = AF_UNSPEC;
+    char                        addr_family_char = '?';
+    const char *                path;
+    gconstpointer               ptr;
+    guint                       i;
+
+    if (self) {
+        addr_family      = nm_ip_config_get_addr_family(self);
+        addr_family_char = nm_utils_addr_family_to_char(addr_family);
+    }
+
+    nm_log(level, domain, NULL, NULL, "---- NMIP%cConfig %p (%s)", addr_family_char, self, detail);
+
+    if (!self)
+        return;
+
+    path = nm_dbus_object_get_path(NM_DBUS_OBJECT(self));
+    if (path)
+        nm_log(level, domain, NULL, NULL, " path     : %s", path);
+
+    if (addr_family == AF_INET) {
+        ip4 = NM_IP4_CONFIG(self);
+        nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, ip4, &addr4) {
+            nm_log(level,
+                   domain,
+                   NULL,
+                   NULL,
+                   " address  : %s",
+                   nm_platform_ip4_address_to_string(addr4, NULL, 0));
+        }
+        nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, ip4, &route4) {
+            nm_log(level,
+                   domain,
+                   NULL,
+                   NULL,
+                   " route    : %s",
+                   nm_platform_ip4_route_to_string(route4, NULL, 0));
+        }
+    } else {
+        ip6 = NM_IP6_CONFIG(self);
+        nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, ip6, &addr6) {
+            nm_log(level,
+                   domain,
+                   NULL,
+                   NULL,
+                   " address  : %s",
+                   nm_platform_ip6_address_to_string(addr6, NULL, 0));
+        }
+        nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, ip6, &route6) {
+            nm_log(level,
+                   domain,
+                   NULL,
+                   NULL,
+                   " route    : %s",
+                   nm_platform_ip6_route_to_string(route6, NULL, 0));
+        }
+    }
+
+    for (i = 0; i < nm_ip_config_get_num_nameservers(self); i++) {
+        char buf[NM_UTILS_INET_ADDRSTRLEN];
+
+        ptr = nm_ip_config_get_nameserver(self, i);
+        nm_log(level,
+               domain,
+               NULL,
+               NULL,
+               " dns      : %s",
+               nm_utils_inet_ntop(addr_family, ptr, buf));
+    }
+
+    for (i = 0; i < nm_ip_config_get_num_domains(self); i++)
+        nm_log(level, domain, NULL, NULL, " domain   : %s", nm_ip_config_get_domain(self, i));
+
+    for (i = 0; i < nm_ip_config_get_num_searches(self); i++)
+        nm_log(level, domain, NULL, NULL, " search   : %s", nm_ip_config_get_search(self, i));
+
+    for (i = 0; i < nm_ip_config_get_num_dns_options(self); i++)
+        nm_log(level, domain, NULL, NULL, "dns-option: %s", nm_ip_config_get_dns_option(self, i));
+
+    nm_log(level, domain, NULL, NULL, " dns-prio : %d", nm_ip_config_get_dns_priority(self));
+
+    if (addr_family == AF_INET) {
+        ip4 = NM_IP4_CONFIG(self);
+        nm_log(level,
+               domain,
+               NULL,
+               NULL,
+               " mtu      : %" G_GUINT32_FORMAT " (source: %d)",
+               nm_ip4_config_get_mtu(ip4),
+               (int) nm_ip4_config_get_mtu_source(ip4));
+        nm_log(level, domain, NULL, NULL, " metered  : %d", (int) nm_ip4_config_get_metered(ip4));
+    }
 }
 
 /*****************************************************************************/
 
 void
-nm_ip4_config_reset_addresses (NMIP4Config *self)
+nm_ip4_config_reset_addresses(NMIP4Config *self)
 {
-	NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+    NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
 
-	if (nm_dedup_multi_index_remove_idx (priv->multi_idx,
-	                                     &priv->idx_ip4_addresses) > 0)
-		_notify_addresses (self);
+    if (nm_dedup_multi_index_remove_idx(priv->multi_idx, &priv->idx_ip4_addresses) > 0)
+        _notify_addresses(self);
 }
 
 static void
-_add_address (NMIP4Config *self, const NMPObject *obj_new, const NMPlatformIP4Address *new)
+_add_address(NMIP4Config *self, const NMPObject *obj_new, const NMPlatformIP4Address *new)
 {
-	NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+    NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
 
-	if (_nm_ip_config_add_obj (priv->multi_idx,
-	                           &priv->idx_ip4_addresses_,
-	                           priv->ifindex,
-	                           obj_new,
-	                           (const NMPlatformObject *) new,
-	                           TRUE,
-	                           FALSE,
-	                           NULL,
-	                           NULL))
-		_notify_addresses (self);
+    if (_nm_ip_config_add_obj(priv->multi_idx,
+                              &priv->idx_ip4_addresses_,
+                              priv->ifindex,
+                              obj_new,
+                              (const NMPlatformObject *) new,
+                              TRUE,
+                              FALSE,
+                              NULL,
+                              NULL))
+        _notify_addresses(self);
 }
 
 /**
@@ -2190,152 +2013,141 @@ _add_address (NMIP4Config *self, const NMPObject *obj_new, const NMPlatformIP4Ad
  * from @new if that source is higher priority.
  */
 void
-nm_ip4_config_add_address (NMIP4Config *self, const NMPlatformIP4Address *new)
+nm_ip4_config_add_address(NMIP4Config *self, const NMPlatformIP4Address *new)
 {
-	g_return_if_fail (self);
-	g_return_if_fail (new);
-	g_return_if_fail (new->plen <= 32);
-	g_return_if_fail (NM_IP4_CONFIG_GET_PRIVATE (self)->ifindex > 0);
+    g_return_if_fail(self);
+    g_return_if_fail(new);
+    g_return_if_fail(new->plen <= 32);
+    g_return_if_fail(NM_IP4_CONFIG_GET_PRIVATE(self)->ifindex > 0);
 
-	_add_address (self, NULL, new);
+    _add_address(self, NULL, new);
 }
 
 void
-_nmtst_ip4_config_del_address (NMIP4Config *self, guint i)
+_nmtst_ip4_config_del_address(NMIP4Config *self, guint i)
 {
-	const NMPlatformIP4Address *a;
+    const NMPlatformIP4Address *a;
 
-	a = _nmtst_ip4_config_get_address (self, i);
-	if (!nm_ip4_config_nmpobj_remove (self,
-	                                  NMP_OBJECT_UP_CAST (a)))
-		g_assert_not_reached ();
+    a = _nmtst_ip4_config_get_address(self, i);
+    if (!nm_ip4_config_nmpobj_remove(self, NMP_OBJECT_UP_CAST(a)))
+        g_assert_not_reached();
 }
 
 guint
-nm_ip4_config_get_num_addresses (const NMIP4Config *self)
+nm_ip4_config_get_num_addresses(const NMIP4Config *self)
 {
-	const NMDedupMultiHeadEntry *head_entry;
+    const NMDedupMultiHeadEntry *head_entry;
 
-	head_entry = nm_ip4_config_lookup_addresses (self);
-	return head_entry ? head_entry->len : 0;
+    head_entry = nm_ip4_config_lookup_addresses(self);
+    return head_entry ? head_entry->len : 0;
 }
 
 const NMPlatformIP4Address *
-nm_ip4_config_get_first_address (const NMIP4Config *self)
+nm_ip4_config_get_first_address(const NMIP4Config *self)
 {
-	NMDedupMultiIter iter;
-	const NMPlatformIP4Address *a = NULL;
+    NMDedupMultiIter            iter;
+    const NMPlatformIP4Address *a = NULL;
 
-	nm_ip_config_iter_ip4_address_for_each (&iter, self, &a)
-		return a;
-	return NULL;
+    nm_ip_config_iter_ip4_address_for_each (&iter, self, &a)
+        return a;
+    return NULL;
 }
 
 const NMPlatformIP4Address *
-_nmtst_ip4_config_get_address (const NMIP4Config *self, guint i)
+_nmtst_ip4_config_get_address(const NMIP4Config *self, guint i)
 {
-	NMDedupMultiIter iter = { };
-	const NMPlatformIP4Address *a = NULL;
-	guint j;
+    NMDedupMultiIter            iter = {};
+    const NMPlatformIP4Address *a    = NULL;
+    guint                       j;
 
-	j = 0;
-	nm_ip_config_iter_ip4_address_for_each (&iter, self, &a) {
-		if (i == j)
-			return a;
-		j++;
-	}
-	g_return_val_if_reached (NULL);
+    j = 0;
+    nm_ip_config_iter_ip4_address_for_each (&iter, self, &a) {
+        if (i == j)
+            return a;
+        j++;
+    }
+    g_return_val_if_reached(NULL);
 }
 
 gboolean
-nm_ip4_config_address_exists (const NMIP4Config *self,
-                              const NMPlatformIP4Address *needle)
+nm_ip4_config_address_exists(const NMIP4Config *self, const NMPlatformIP4Address *needle)
 {
-	const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
-	NMPObject obj_stack;
+    const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
+    NMPObject                 obj_stack;
 
-	nmp_object_stackinit_id_ip4_address (&obj_stack,
-	                                     priv->ifindex,
-	                                     needle->address,
-	                                     needle->plen,
-	                                     needle->peer_address);
-	return !!nm_dedup_multi_index_lookup_obj (priv->multi_idx,
-	                                          &priv->idx_ip4_addresses,
-	                                          &obj_stack);
+    nmp_object_stackinit_id_ip4_address(&obj_stack,
+                                        priv->ifindex,
+                                        needle->address,
+                                        needle->plen,
+                                        needle->peer_address);
+    return !!nm_dedup_multi_index_lookup_obj(priv->multi_idx, &priv->idx_ip4_addresses, &obj_stack);
 }
 
 /*****************************************************************************/
 
 static const NMDedupMultiEntry *
-_lookup_route (const NMIP4Config *self,
-               const NMPObject *needle,
-               NMPlatformIPRouteCmpType cmp_type)
+_lookup_route(const NMIP4Config *self, const NMPObject *needle, NMPlatformIPRouteCmpType cmp_type)
 {
-	const NMIP4ConfigPrivate *priv;
+    const NMIP4ConfigPrivate *priv;
 
-	nm_assert (NM_IS_IP4_CONFIG (self));
-	nm_assert (NMP_OBJECT_GET_TYPE (needle) == NMP_OBJECT_TYPE_IP4_ROUTE);
+    nm_assert(NM_IS_IP4_CONFIG(self));
+    nm_assert(NMP_OBJECT_GET_TYPE(needle) == NMP_OBJECT_TYPE_IP4_ROUTE);
 
-	priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+    priv = NM_IP4_CONFIG_GET_PRIVATE(self);
 
-	return _nm_ip_config_lookup_ip_route (priv->multi_idx,
-	                                      &priv->idx_ip4_routes_,
-	                                      needle,
-	                                      cmp_type);
+    return _nm_ip_config_lookup_ip_route(priv->multi_idx, &priv->idx_ip4_routes_, needle, cmp_type);
 }
 
 void
-nm_ip4_config_reset_routes (NMIP4Config *self)
+nm_ip4_config_reset_routes(NMIP4Config *self)
 {
-	NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+    NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
 
-	if (nm_dedup_multi_index_remove_idx (priv->multi_idx,
-	                                     &priv->idx_ip4_routes) > 0) {
-		if (nm_clear_nmp_object (&priv->best_default_route))
-			_notify (self, PROP_GATEWAY);
-		_notify_routes (self);
-	}
+    if (nm_dedup_multi_index_remove_idx(priv->multi_idx, &priv->idx_ip4_routes) > 0) {
+        if (nm_clear_nmp_object(&priv->best_default_route))
+            _notify(self, PROP_GATEWAY);
+        _notify_routes(self);
+    }
 }
 
 static void
-_add_route (NMIP4Config *self,
-            const NMPObject *obj_new,
-            const NMPlatformIP4Route *new,
-            const NMPObject **out_obj_new)
-{
-	NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
-	nm_auto_nmpobj const NMPObject *obj_old = NULL;
-	const NMPObject *obj_new_2;
-
-	nm_assert ((!new) != (!obj_new));
-	nm_assert (!new || _route_valid (new));
-	nm_assert (!obj_new || _route_valid (NMP_OBJECT_CAST_IP4_ROUTE (obj_new)));
-
-	if (_nm_ip_config_add_obj (priv->multi_idx,
-	                           &priv->idx_ip4_routes_,
-	                           priv->ifindex,
-	                           obj_new,
-	                           (const NMPlatformObject *) new,
-	                           TRUE,
-	                           FALSE,
-	                           &obj_old,
-	                           &obj_new_2)) {
-		gboolean changed_default_route = FALSE;
-
-		if (   priv->best_default_route == obj_old
-		    && obj_old != obj_new_2) {
-			changed_default_route = TRUE;
-			nm_clear_nmp_object (&priv->best_default_route);
-		}
-		NM_SET_OUT (out_obj_new, nmp_object_ref (obj_new_2));
-		if (_nm_ip_config_best_default_route_merge (&priv->best_default_route, obj_new_2))
-			changed_default_route = TRUE;
-
-		if (changed_default_route)
-			_notify (self, PROP_GATEWAY);
-		_notify_routes (self);
-	} else
-		NM_SET_OUT (out_obj_new, nmp_object_ref (obj_new_2));
+_add_route(NMIP4Config *    self,
+           const NMPObject *obj_new,
+           const NMPlatformIP4Route *new,
+           const NMPObject **out_obj_new)
+{
+    NMIP4ConfigPrivate * priv               = NM_IP4_CONFIG_GET_PRIVATE(self);
+    nm_auto_nmpobj const NMPObject *obj_old = NULL;
+    const NMPObject *               obj_new_2;
+
+    nm_assert((!new) != (!obj_new));
+    nm_assert(!new || _route_valid(new));
+    nm_assert(!obj_new || _route_valid(NMP_OBJECT_CAST_IP4_ROUTE(obj_new)));
+
+    if (_nm_ip_config_add_obj(priv->multi_idx,
+                              &priv->idx_ip4_routes_,
+                              priv->ifindex,
+                              obj_new,
+                              (const NMPlatformObject *) new,
+                              TRUE,
+                              FALSE,
+                              &obj_old,
+                              &obj_new_2)) {
+        gboolean changed_default_route = FALSE;
+
+        if (priv->best_default_route == obj_old && obj_old != obj_new_2) {
+            changed_default_route = TRUE;
+            nm_clear_nmp_object(&priv->best_default_route);
+        }
+        NM_SET_OUT(out_obj_new, nmp_object_ref(obj_new_2));
+        if (_nm_ip_config_best_default_route_merge(&priv->best_default_route, obj_new_2))
+            changed_default_route = TRUE;
+
+        if (changed_default_route)
+            _notify(self, PROP_GATEWAY);
+        _notify_routes(self);
+    } else
+        NM_SET_OUT(out_obj_new, nmp_object_ref(obj_new_2));
 }
 
 /**
@@ -2351,739 +2163,729 @@ _add_route (NMIP4Config *self,
  * from @new if that source is higher priority.
  */
 void
-nm_ip4_config_add_route (NMIP4Config *self,
-                         const NMPlatformIP4Route *new,
-                         const NMPObject **out_obj_new)
+nm_ip4_config_add_route(NMIP4Config *self,
+                        const NMPlatformIP4Route *new,
+                        const NMPObject **out_obj_new)
 {
-	g_return_if_fail (self);
-	g_return_if_fail (new);
-	g_return_if_fail (new->plen <= 32);
-	g_return_if_fail (NM_IP4_CONFIG_GET_PRIVATE (self)->ifindex > 0);
+    g_return_if_fail(self);
+    g_return_if_fail(new);
+    g_return_if_fail(new->plen <= 32);
+    g_return_if_fail(NM_IP4_CONFIG_GET_PRIVATE(self)->ifindex > 0);
 
-	_add_route (self, NULL, new, out_obj_new);
+    _add_route(self, NULL, new, out_obj_new);
 }
 
 void
-_nmtst_ip4_config_del_route (NMIP4Config *self, guint i)
+_nmtst_ip4_config_del_route(NMIP4Config *self, guint i)
 {
-	const NMPlatformIP4Route *r;
+    const NMPlatformIP4Route *r;
 
-	r = _nmtst_ip4_config_get_route (self, i);
-	if (!nm_ip4_config_nmpobj_remove (self,
-	                                  NMP_OBJECT_UP_CAST (r)))
-		g_assert_not_reached ();
+    r = _nmtst_ip4_config_get_route(self, i);
+    if (!nm_ip4_config_nmpobj_remove(self, NMP_OBJECT_UP_CAST(r)))
+        g_assert_not_reached();
 }
 
 guint
-nm_ip4_config_get_num_routes (const NMIP4Config *self)
+nm_ip4_config_get_num_routes(const NMIP4Config *self)
 {
-	const NMDedupMultiHeadEntry *head_entry;
+    const NMDedupMultiHeadEntry *head_entry;
 
-	head_entry = nm_ip4_config_lookup_routes (self);
-	nm_assert (!head_entry || head_entry->len == c_list_length (&head_entry->lst_entries_head));
-	return head_entry ? head_entry->len : 0;
+    head_entry = nm_ip4_config_lookup_routes(self);
+    nm_assert(!head_entry || head_entry->len == c_list_length(&head_entry->lst_entries_head));
+    return head_entry ? head_entry->len : 0;
 }
 
 const NMPlatformIP4Route *
-_nmtst_ip4_config_get_route (const NMIP4Config *self, guint i)
+_nmtst_ip4_config_get_route(const NMIP4Config *self, guint i)
 {
-	NMDedupMultiIter iter;
-	const NMPlatformIP4Route *r = NULL;
-	guint j;
+    NMDedupMultiIter          iter;
+    const NMPlatformIP4Route *r = NULL;
+    guint                     j;
 
-	j = 0;
-	nm_ip_config_iter_ip4_route_for_each (&iter, self, &r) {
-		if (i == j)
-			return r;
-		j++;
-	}
-	g_return_val_if_reached (NULL);
+    j = 0;
+    nm_ip_config_iter_ip4_route_for_each (&iter, self, &r) {
+        if (i == j)
+            return r;
+        j++;
+    }
+    g_return_val_if_reached(NULL);
 }
 
 const NMPlatformIP4Route *
-nm_ip4_config_get_direct_route_for_host (const NMIP4Config *self,
-                                         in_addr_t host,
-                                         guint32 route_table)
+nm_ip4_config_get_direct_route_for_host(const NMIP4Config *self,
+                                        in_addr_t          host,
+                                        guint32            route_table)
 {
-	const NMPlatformIP4Route *best_route = NULL;
-	const NMPlatformIP4Route *item;
-	NMDedupMultiIter ipconf_iter;
+    const NMPlatformIP4Route *best_route = NULL;
+    const NMPlatformIP4Route *item;
+    NMDedupMultiIter          ipconf_iter;
 
-	g_return_val_if_fail (host, NULL);
+    g_return_val_if_fail(host, NULL);
 
-	nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, self, &item) {
-		if (item->gateway != 0)
-			continue;
+    nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, self, &item) {
+        if (item->gateway != 0)
+            continue;
 
-		if (best_route && best_route->plen > item->plen)
-			continue;
+        if (best_route && best_route->plen > item->plen)
+            continue;
 
-		if (nm_platform_route_table_uncoerce (item->table_coerced, TRUE) != route_table)
-			continue;
+        if (nm_platform_route_table_uncoerce(item->table_coerced, TRUE) != route_table)
+            continue;
 
-		if (nm_utils_ip4_address_clear_host_address (host, item->plen) != nm_utils_ip4_address_clear_host_address (item->network, item->plen))
-			continue;
+        if (nm_utils_ip4_address_clear_host_address(host, item->plen)
+            != nm_utils_ip4_address_clear_host_address(item->network, item->plen))
+            continue;
 
-		if (best_route && best_route->metric <= item->metric)
-			continue;
+        if (best_route && best_route->metric <= item->metric)
+            continue;
 
-		best_route = item;
-	}
-	return best_route;
+        best_route = item;
+    }
+    return best_route;
 }
 
 /*****************************************************************************/
 
 void
-nm_ip4_config_reset_nameservers (NMIP4Config *self)
+nm_ip4_config_reset_nameservers(NMIP4Config *self)
 {
-	NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+    NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
 
-	if (priv->nameservers->len != 0) {
-		g_array_set_size (priv->nameservers, 0);
-		nm_gobject_notify_together (self, PROP_NAMESERVER_DATA,
-		                                  PROP_NAMESERVERS);
-	}
+    if (priv->nameservers->len != 0) {
+        g_array_set_size(priv->nameservers, 0);
+        nm_gobject_notify_together(self, PROP_NAMESERVER_DATA, PROP_NAMESERVERS);
+    }
 }
 
 void
-nm_ip4_config_add_nameserver (NMIP4Config *self, guint32 new)
+nm_ip4_config_add_nameserver(NMIP4Config *self, guint32 new)
 {
-	NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
-	int i;
+    NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
+    int                 i;
 
-	g_return_if_fail (new != 0);
+    g_return_if_fail(new != 0);
 
-	for (i = 0; i < priv->nameservers->len; i++)
-		if (new == g_array_index (priv->nameservers, guint32, i))
-			return;
+    for (i = 0; i < priv->nameservers->len; i++)
+        if (new == g_array_index(priv->nameservers, guint32, i))
+            return;
 
-	g_array_append_val (priv->nameservers, new);
-	nm_gobject_notify_together (self, PROP_NAMESERVER_DATA,
-	                                  PROP_NAMESERVERS);
+    g_array_append_val(priv->nameservers, new);
+    nm_gobject_notify_together(self, PROP_NAMESERVER_DATA, PROP_NAMESERVERS);
 }
 
 void
-nm_ip4_config_del_nameserver (NMIP4Config *self, guint i)
+nm_ip4_config_del_nameserver(NMIP4Config *self, guint i)
 {
-	NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+    NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
 
-	g_return_if_fail (i < priv->nameservers->len);
+    g_return_if_fail(i < priv->nameservers->len);
 
-	g_array_remove_index (priv->nameservers, i);
-	nm_gobject_notify_together (self, PROP_NAMESERVER_DATA,
-	                                  PROP_NAMESERVERS);
+    g_array_remove_index(priv->nameservers, i);
+    nm_gobject_notify_together(self, PROP_NAMESERVER_DATA, PROP_NAMESERVERS);
 }
 
 guint
-nm_ip4_config_get_num_nameservers (const NMIP4Config *self)
+nm_ip4_config_get_num_nameservers(const NMIP4Config *self)
 {
-	const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+    const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
 
-	return priv->nameservers->len;
+    return priv->nameservers->len;
 }
 
 guint32
-nm_ip4_config_get_nameserver (const NMIP4Config *self, guint i)
+nm_ip4_config_get_nameserver(const NMIP4Config *self, guint i)
 {
-	const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+    const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
 
-	return g_array_index (priv->nameservers, guint32, i);
+    return g_array_index(priv->nameservers, guint32, i);
 }
 
 const in_addr_t *
-_nm_ip4_config_get_nameserver (const NMIP4Config *self, guint i)
+_nm_ip4_config_get_nameserver(const NMIP4Config *self, guint i)
 {
-	const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+    const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
 
-	return &g_array_index (priv->nameservers, guint32, i);
+    return &g_array_index(priv->nameservers, guint32, i);
 }
 
 /*****************************************************************************/
 
 gboolean
-_nm_ip_config_check_and_add_domain (GPtrArray *array, const char *domain)
+_nm_ip_config_check_and_add_domain(GPtrArray *array, const char *domain)
 {
-	char *copy = NULL;
-	size_t len;
+    char * copy = NULL;
+    size_t len;
 
-	g_return_val_if_fail (domain, FALSE);
-	g_return_val_if_fail (domain[0] != '\0', FALSE);
+    g_return_val_if_fail(domain, FALSE);
+    g_return_val_if_fail(domain[0] != '\0', FALSE);
 
-	if (domain[0] == '.' || strstr (domain, ".."))
-		return FALSE;
+    if (domain[0] == '.' || strstr(domain, ".."))
+        return FALSE;
 
-	len = strlen (domain);
-	if (domain[len - 1] == '.')
-		domain = copy = g_strndup (domain, len - 1);
+    len = strlen(domain);
+    if (domain[len - 1] == '.')
+        domain = copy = g_strndup(domain, len - 1);
 
-	if (nm_utils_strv_find_first ((char **) array->pdata, array->len, domain) >= 0) {
-		g_free (copy);
-		return FALSE;
-	}
+    if (nm_utils_strv_find_first((char **) array->pdata, array->len, domain) >= 0) {
+        g_free(copy);
+        return FALSE;
+    }
 
-	g_ptr_array_add (array, copy ?: g_strdup (domain));
-	return TRUE;
+    g_ptr_array_add(array, copy ?: g_strdup(domain));
+    return TRUE;
 }
 
 void
-nm_ip4_config_reset_domains (NMIP4Config *self)
+nm_ip4_config_reset_domains(NMIP4Config *self)
 {
-	NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+    NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
 
-	if (priv->domains->len != 0) {
-		g_ptr_array_set_size (priv->domains, 0);
-		_notify (self, PROP_DOMAINS);
-	}
+    if (priv->domains->len != 0) {
+        g_ptr_array_set_size(priv->domains, 0);
+        _notify(self, PROP_DOMAINS);
+    }
 }
 
 void
-nm_ip4_config_add_domain (NMIP4Config *self, const char *domain)
+nm_ip4_config_add_domain(NMIP4Config *self, const char *domain)
 {
-	NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+    NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
 
-	if (_nm_ip_config_check_and_add_domain (priv->domains, domain))
-		_notify (self, PROP_DOMAINS);
+    if (_nm_ip_config_check_and_add_domain(priv->domains, domain))
+        _notify(self, PROP_DOMAINS);
 }
 
 void
-nm_ip4_config_del_domain (NMIP4Config *self, guint i)
+nm_ip4_config_del_domain(NMIP4Config *self, guint i)
 {
-	NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+    NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
 
-	g_return_if_fail (i < priv->domains->len);
+    g_return_if_fail(i < priv->domains->len);
 
-	g_ptr_array_remove_index (priv->domains, i);
-	_notify (self, PROP_DOMAINS);
+    g_ptr_array_remove_index(priv->domains, i);
+    _notify(self, PROP_DOMAINS);
 }
 
 guint
-nm_ip4_config_get_num_domains (const NMIP4Config *self)
+nm_ip4_config_get_num_domains(const NMIP4Config *self)
 {
-	const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+    const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
 
-	return priv->domains->len;
+    return priv->domains->len;
 }
 
 const char *
-nm_ip4_config_get_domain (const NMIP4Config *self, guint i)
+nm_ip4_config_get_domain(const NMIP4Config *self, guint i)
 {
-	const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+    const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
 
-	return g_ptr_array_index (priv->domains, i);
+    return g_ptr_array_index(priv->domains, i);
 }
 
 /*****************************************************************************/
 
 void
-nm_ip4_config_reset_searches (NMIP4Config *self)
+nm_ip4_config_reset_searches(NMIP4Config *self)
 {
-	NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+    NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
 
-	if (priv->searches->len != 0) {
-		g_ptr_array_set_size (priv->searches, 0);
-		_notify (self, PROP_SEARCHES);
-	}
+    if (priv->searches->len != 0) {
+        g_ptr_array_set_size(priv->searches, 0);
+        _notify(self, PROP_SEARCHES);
+    }
 }
 
 void
-nm_ip4_config_add_search (NMIP4Config *self, const char *search)
+nm_ip4_config_add_search(NMIP4Config *self, const char *search)
 {
-	NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+    NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
 
-	if (_nm_ip_config_check_and_add_domain (priv->searches, search))
-		_notify (self, PROP_SEARCHES);
+    if (_nm_ip_config_check_and_add_domain(priv->searches, search))
+        _notify(self, PROP_SEARCHES);
 }
 
 void
-nm_ip4_config_del_search (NMIP4Config *self, guint i)
+nm_ip4_config_del_search(NMIP4Config *self, guint i)
 {
-	NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+    NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
 
-	g_return_if_fail (i < priv->searches->len);
+    g_return_if_fail(i < priv->searches->len);
 
-	g_ptr_array_remove_index (priv->searches, i);
-	_notify (self, PROP_SEARCHES);
+    g_ptr_array_remove_index(priv->searches, i);
+    _notify(self, PROP_SEARCHES);
 }
 
 guint
-nm_ip4_config_get_num_searches (const NMIP4Config *self)
+nm_ip4_config_get_num_searches(const NMIP4Config *self)
 {
-	const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+    const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
 
-	return priv->searches->len;
+    return priv->searches->len;
 }
 
 const char *
-nm_ip4_config_get_search (const NMIP4Config *self, guint i)
+nm_ip4_config_get_search(const NMIP4Config *self, guint i)
 {
-	const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+    const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
 
-	return g_ptr_array_index (priv->searches, i);
+    return g_ptr_array_index(priv->searches, i);
 }
 
 /*****************************************************************************/
 
 void
-nm_ip4_config_reset_dns_options (NMIP4Config *self)
+nm_ip4_config_reset_dns_options(NMIP4Config *self)
 {
-	NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+    NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
 
-	if (priv->dns_options->len != 0) {
-		g_ptr_array_set_size (priv->dns_options, 0);
-		_notify (self, PROP_DNS_OPTIONS);
-	}
+    if (priv->dns_options->len != 0) {
+        g_ptr_array_set_size(priv->dns_options, 0);
+        _notify(self, PROP_DNS_OPTIONS);
+    }
 }
 
 void
-nm_ip4_config_add_dns_option (NMIP4Config *self, const char *new)
+nm_ip4_config_add_dns_option(NMIP4Config *self, const char *new)
 {
-	NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
-	int i;
+    NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
+    int                 i;
 
-	g_return_if_fail (new != NULL);
-	g_return_if_fail (new[0] != '\0');
+    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;
+    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 (self, PROP_DNS_OPTIONS);
+    g_ptr_array_add(priv->dns_options, g_strdup(new));
+    _notify(self, PROP_DNS_OPTIONS);
 }
 
 void
 nm_ip4_config_del_dns_option(NMIP4Config *self, guint i)
 {
-	NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+    NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
 
-	g_return_if_fail (i < priv->dns_options->len);
+    g_return_if_fail(i < priv->dns_options->len);
 
-	g_ptr_array_remove_index (priv->dns_options, i);
-	_notify (self, PROP_DNS_OPTIONS);
+    g_ptr_array_remove_index(priv->dns_options, i);
+    _notify(self, PROP_DNS_OPTIONS);
 }
 
 guint
-nm_ip4_config_get_num_dns_options (const NMIP4Config *self)
+nm_ip4_config_get_num_dns_options(const NMIP4Config *self)
 {
-	const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+    const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
 
-	return priv->dns_options->len;
+    return priv->dns_options->len;
 }
 
 const char *
-nm_ip4_config_get_dns_option (const NMIP4Config *self, guint i)
+nm_ip4_config_get_dns_option(const NMIP4Config *self, guint i)
 {
-	const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+    const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
 
-	return g_ptr_array_index (priv->dns_options, i);
+    return g_ptr_array_index(priv->dns_options, i);
 }
 
 /*****************************************************************************/
 
 NMSettingConnectionMdns
-nm_ip4_config_mdns_get (const NMIP4Config *self)
+nm_ip4_config_mdns_get(const NMIP4Config *self)
 {
-	return NM_IP4_CONFIG_GET_PRIVATE (self)->mdns;
+    return NM_IP4_CONFIG_GET_PRIVATE(self)->mdns;
 }
 
 void
-nm_ip4_config_mdns_set (NMIP4Config *self,
-                        NMSettingConnectionMdns mdns)
+nm_ip4_config_mdns_set(NMIP4Config *self, NMSettingConnectionMdns mdns)
 {
-	NM_IP4_CONFIG_GET_PRIVATE (self)->mdns = mdns;
+    NM_IP4_CONFIG_GET_PRIVATE(self)->mdns = mdns;
 }
 
 NMSettingConnectionLlmnr
-nm_ip4_config_llmnr_get (const NMIP4Config *self)
+nm_ip4_config_llmnr_get(const NMIP4Config *self)
 {
-	return NM_IP4_CONFIG_GET_PRIVATE (self)->llmnr;
+    return NM_IP4_CONFIG_GET_PRIVATE(self)->llmnr;
 }
 
 void
-nm_ip4_config_llmnr_set (NMIP4Config *self,
-                         NMSettingConnectionLlmnr llmnr)
+nm_ip4_config_llmnr_set(NMIP4Config *self, NMSettingConnectionLlmnr llmnr)
 {
-	NM_IP4_CONFIG_GET_PRIVATE (self)->llmnr = llmnr;
+    NM_IP4_CONFIG_GET_PRIVATE(self)->llmnr = llmnr;
 }
 
 /*****************************************************************************/
 
 NMIPConfigFlags
-nm_ip4_config_get_config_flags (const NMIP4Config *self)
+nm_ip4_config_get_config_flags(const NMIP4Config *self)
 {
-	return NM_IP4_CONFIG_GET_PRIVATE (self)->config_flags;
+    return NM_IP4_CONFIG_GET_PRIVATE(self)->config_flags;
 }
 
 void
-nm_ip4_config_set_config_flags (NMIP4Config *self, NMIPConfigFlags flags, NMIPConfigFlags mask)
+nm_ip4_config_set_config_flags(NMIP4Config *self, NMIPConfigFlags flags, NMIPConfigFlags mask)
 {
-	NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+    NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
 
-	if (mask == 0) {
-		/* for convenience, accept 0 mask to set any flags. */
-		mask = flags;
-	}
+    if (mask == 0) {
+        /* for convenience, accept 0 mask to set any flags. */
+        mask = flags;
+    }
 
-	nm_assert (!NM_FLAGS_ANY (flags, ~mask));
-	priv->config_flags = (flags & mask) | (priv->config_flags & ~mask);
+    nm_assert(!NM_FLAGS_ANY(flags, ~mask));
+    priv->config_flags = (flags & mask) | (priv->config_flags & ~mask);
 }
 
 /*****************************************************************************/
 
 void
-nm_ip4_config_set_dns_priority (NMIP4Config *self, int priority)
+nm_ip4_config_set_dns_priority(NMIP4Config *self, int priority)
 {
-	NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+    NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
 
-	if (priority != priv->dns_priority) {
-		priv->dns_priority = priority;
-		_notify (self, PROP_DNS_PRIORITY);
-	}
+    if (priority != priv->dns_priority) {
+        priv->dns_priority = priority;
+        _notify(self, PROP_DNS_PRIORITY);
+    }
 }
 
 int
-nm_ip4_config_get_dns_priority (const NMIP4Config *self)
+nm_ip4_config_get_dns_priority(const NMIP4Config *self)
 {
-	const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+    const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
 
-	return priv->dns_priority;
+    return priv->dns_priority;
 }
 
 /*****************************************************************************/
 
 void
-nm_ip4_config_reset_nis_servers (NMIP4Config *self)
+nm_ip4_config_reset_nis_servers(NMIP4Config *self)
 {
-	NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+    NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
 
-	g_array_set_size (priv->nis, 0);
+    g_array_set_size(priv->nis, 0);
 }
 
 void
-nm_ip4_config_add_nis_server (NMIP4Config *self, guint32 nis)
+nm_ip4_config_add_nis_server(NMIP4Config *self, guint32 nis)
 {
-	NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
-	int i;
+    NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
+    int                 i;
 
-	for (i = 0; i < priv->nis->len; i++)
-		if (nis == g_array_index (priv->nis, guint32, i))
-			return;
+    for (i = 0; i < priv->nis->len; i++)
+        if (nis == g_array_index(priv->nis, guint32, i))
+            return;
 
-	g_array_append_val (priv->nis, nis);
+    g_array_append_val(priv->nis, nis);
 }
 
 void
-nm_ip4_config_del_nis_server (NMIP4Config *self, guint i)
+nm_ip4_config_del_nis_server(NMIP4Config *self, guint i)
 {
-	NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+    NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
 
-	g_return_if_fail (i < priv->nis->len);
+    g_return_if_fail(i < priv->nis->len);
 
-	g_array_remove_index (priv->nis, i);
+    g_array_remove_index(priv->nis, i);
 }
 
 guint
-nm_ip4_config_get_num_nis_servers (const NMIP4Config *self)
+nm_ip4_config_get_num_nis_servers(const NMIP4Config *self)
 {
-	const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+    const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
 
-	return priv->nis->len;
+    return priv->nis->len;
 }
 
 guint32
-nm_ip4_config_get_nis_server (const NMIP4Config *self, guint i)
+nm_ip4_config_get_nis_server(const NMIP4Config *self, guint i)
 {
-	const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+    const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
 
-	return g_array_index (priv->nis, guint32, i);
+    return g_array_index(priv->nis, guint32, i);
 }
 
 void
-nm_ip4_config_set_nis_domain (NMIP4Config *self, const char *domain)
+nm_ip4_config_set_nis_domain(NMIP4Config *self, const char *domain)
 {
-	NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+    NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
 
-	g_free (priv->nis_domain);
-	priv->nis_domain = g_strdup (domain);
+    g_free(priv->nis_domain);
+    priv->nis_domain = g_strdup(domain);
 }
 
 const char *
-nm_ip4_config_get_nis_domain (const NMIP4Config *self)
+nm_ip4_config_get_nis_domain(const NMIP4Config *self)
 {
-	const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+    const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
 
-	return priv->nis_domain;
+    return priv->nis_domain;
 }
 
 /*****************************************************************************/
 
 void
-nm_ip4_config_reset_wins (NMIP4Config *self)
+nm_ip4_config_reset_wins(NMIP4Config *self)
 {
-	NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+    NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
 
-	if (priv->wins->len != 0) {
-		g_array_set_size (priv->wins, 0);
-		nm_gobject_notify_together (self, PROP_WINS_SERVER_DATA,
-		                                  PROP_WINS_SERVERS);
-	}
+    if (priv->wins->len != 0) {
+        g_array_set_size(priv->wins, 0);
+        nm_gobject_notify_together(self, PROP_WINS_SERVER_DATA, PROP_WINS_SERVERS);
+    }
 }
 
 void
-nm_ip4_config_add_wins (NMIP4Config *self, guint32 wins)
+nm_ip4_config_add_wins(NMIP4Config *self, guint32 wins)
 {
-	NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
-	int i;
+    NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
+    int                 i;
 
-	g_return_if_fail (wins != 0);
+    g_return_if_fail(wins != 0);
 
-	for (i = 0; i < priv->wins->len; i++)
-		if (wins == g_array_index (priv->wins, guint32, i))
-			return;
+    for (i = 0; i < priv->wins->len; i++)
+        if (wins == g_array_index(priv->wins, guint32, i))
+            return;
 
-	g_array_append_val (priv->wins, wins);
-	nm_gobject_notify_together (self, PROP_WINS_SERVER_DATA,
-	                                  PROP_WINS_SERVERS);
+    g_array_append_val(priv->wins, wins);
+    nm_gobject_notify_together(self, PROP_WINS_SERVER_DATA, PROP_WINS_SERVERS);
 }
 
 void
-nm_ip4_config_del_wins (NMIP4Config *self, guint i)
+nm_ip4_config_del_wins(NMIP4Config *self, guint i)
 {
-	NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+    NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
 
-	g_return_if_fail (i < priv->wins->len);
+    g_return_if_fail(i < priv->wins->len);
 
-	g_array_remove_index (priv->wins, i);
-	nm_gobject_notify_together (self, PROP_WINS_SERVER_DATA,
-	                                  PROP_WINS_SERVERS);
+    g_array_remove_index(priv->wins, i);
+    nm_gobject_notify_together(self, PROP_WINS_SERVER_DATA, PROP_WINS_SERVERS);
 }
 
 guint
-nm_ip4_config_get_num_wins (const NMIP4Config *self)
+nm_ip4_config_get_num_wins(const NMIP4Config *self)
 {
-	const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+    const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
 
-	return priv->wins->len;
+    return priv->wins->len;
 }
 
 guint32
-nm_ip4_config_get_wins (const NMIP4Config *self, guint i)
+nm_ip4_config_get_wins(const NMIP4Config *self, guint i)
 {
-	const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+    const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
 
-	return g_array_index (priv->wins, guint32, i);
+    return g_array_index(priv->wins, guint32, i);
 }
 
 /*****************************************************************************/
 
 void
-nm_ip4_config_set_mtu (NMIP4Config *self, guint32 mtu, NMIPConfigSource source)
+nm_ip4_config_set_mtu(NMIP4Config *self, guint32 mtu, NMIPConfigSource source)
 {
-	NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+    NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
 
-	if (!mtu)
-		source = NM_IP_CONFIG_SOURCE_UNKNOWN;
+    if (!mtu)
+        source = NM_IP_CONFIG_SOURCE_UNKNOWN;
 
-	priv->mtu = mtu;
-	priv->mtu_source = source;
+    priv->mtu        = mtu;
+    priv->mtu_source = source;
 }
 
 guint32
-nm_ip4_config_get_mtu (const NMIP4Config *self)
+nm_ip4_config_get_mtu(const NMIP4Config *self)
 {
-	const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+    const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
 
-	return priv->mtu;
+    return priv->mtu;
 }
 
 NMIPConfigSource
-nm_ip4_config_get_mtu_source (const NMIP4Config *self)
+nm_ip4_config_get_mtu_source(const NMIP4Config *self)
 {
-	const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+    const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
 
-	return priv->mtu_source;
+    return priv->mtu_source;
 }
 
 /*****************************************************************************/
 
 void
-nm_ip4_config_set_metered (NMIP4Config *self, gboolean metered)
+nm_ip4_config_set_metered(NMIP4Config *self, gboolean metered)
 {
-	NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+    NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
 
-	priv->metered = metered;
+    priv->metered = metered;
 }
 
 gboolean
-nm_ip4_config_get_metered (const NMIP4Config *self)
+nm_ip4_config_get_metered(const NMIP4Config *self)
 {
-	const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+    const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
 
-	return priv->metered;
+    return priv->metered;
 }
 
 /*****************************************************************************/
 
 const NMPObject *
-nm_ip4_config_nmpobj_lookup (const NMIP4Config *self, const NMPObject *needle)
+nm_ip4_config_nmpobj_lookup(const NMIP4Config *self, const NMPObject *needle)
 {
-	const NMIP4ConfigPrivate *priv;
-	const NMDedupMultiIdxType *idx_type;
+    const NMIP4ConfigPrivate * priv;
+    const NMDedupMultiIdxType *idx_type;
 
-	g_return_val_if_fail (NM_IS_IP4_CONFIG (self), NULL);
+    g_return_val_if_fail(NM_IS_IP4_CONFIG(self), NULL);
 
-	priv = NM_IP4_CONFIG_GET_PRIVATE (self);
-	switch (NMP_OBJECT_GET_TYPE (needle)) {
-	case NMP_OBJECT_TYPE_IP4_ADDRESS:
-		idx_type = &priv->idx_ip4_addresses;
-		break;
-	case NMP_OBJECT_TYPE_IP4_ROUTE:
-		idx_type = &priv->idx_ip4_routes;
-		break;
-	default:
-		g_return_val_if_reached (NULL);
-	}
+    priv = NM_IP4_CONFIG_GET_PRIVATE(self);
+    switch (NMP_OBJECT_GET_TYPE(needle)) {
+    case NMP_OBJECT_TYPE_IP4_ADDRESS:
+        idx_type = &priv->idx_ip4_addresses;
+        break;
+    case NMP_OBJECT_TYPE_IP4_ROUTE:
+        idx_type = &priv->idx_ip4_routes;
+        break;
+    default:
+        g_return_val_if_reached(NULL);
+    }
 
-	return nm_dedup_multi_entry_get_obj (nm_dedup_multi_index_lookup_obj (priv->multi_idx,
-	                                                                      idx_type,
-	                                                                      needle));
+    return nm_dedup_multi_entry_get_obj(
+        nm_dedup_multi_index_lookup_obj(priv->multi_idx, idx_type, needle));
 }
 
 gboolean
-nm_ip4_config_nmpobj_remove (NMIP4Config *self,
-                             const NMPObject *needle)
-{
-	NMIP4ConfigPrivate *priv;
-	NMDedupMultiIdxType *idx_type;
-	nm_auto_nmpobj const NMPObject *obj_old = NULL;
-	guint n;
-
-	g_return_val_if_fail (NM_IS_IP4_CONFIG (self), FALSE);
-
-	priv = NM_IP4_CONFIG_GET_PRIVATE (self);
-	switch (NMP_OBJECT_GET_TYPE (needle)) {
-	case NMP_OBJECT_TYPE_IP4_ADDRESS:
-		idx_type = &priv->idx_ip4_addresses;
-		break;
-	case NMP_OBJECT_TYPE_IP4_ROUTE:
-		idx_type = &priv->idx_ip4_routes;
-		break;
-	default:
-		g_return_val_if_reached (FALSE);
-	}
-
-	n = nm_dedup_multi_index_remove_obj (priv->multi_idx,
-	                                     idx_type,
-	                                     needle,
-	                                     (gconstpointer *) &obj_old);
-	if (n != 1) {
-		nm_assert (n == 0);
-		return FALSE;
-	}
-
-	nm_assert (NMP_OBJECT_GET_TYPE (obj_old) == NMP_OBJECT_GET_TYPE (needle));
-
-	switch (NMP_OBJECT_GET_TYPE (obj_old)) {
-	case NMP_OBJECT_TYPE_IP4_ADDRESS:
-		_notify_addresses (self);
-		break;
-	case NMP_OBJECT_TYPE_IP4_ROUTE:
-		if (priv->best_default_route == obj_old) {
-			if (_nm_ip_config_best_default_route_set (&priv->best_default_route,
-			                                          _nm_ip4_config_best_default_route_find (self)))
-				_notify (self, PROP_GATEWAY);
-		}
-		_notify_routes (self);
-		break;
-	default:
-		nm_assert_not_reached ();
-	}
-	return TRUE;
+nm_ip4_config_nmpobj_remove(NMIP4Config *self, const NMPObject *needle)
+{
+    NMIP4ConfigPrivate * priv;
+    NMDedupMultiIdxType *idx_type;
+    nm_auto_nmpobj const NMPObject *obj_old = NULL;
+    guint                           n;
+
+    g_return_val_if_fail(NM_IS_IP4_CONFIG(self), FALSE);
+
+    priv = NM_IP4_CONFIG_GET_PRIVATE(self);
+    switch (NMP_OBJECT_GET_TYPE(needle)) {
+    case NMP_OBJECT_TYPE_IP4_ADDRESS:
+        idx_type = &priv->idx_ip4_addresses;
+        break;
+    case NMP_OBJECT_TYPE_IP4_ROUTE:
+        idx_type = &priv->idx_ip4_routes;
+        break;
+    default:
+        g_return_val_if_reached(FALSE);
+    }
+
+    n = nm_dedup_multi_index_remove_obj(priv->multi_idx,
+                                        idx_type,
+                                        needle,
+                                        (gconstpointer *) &obj_old);
+    if (n != 1) {
+        nm_assert(n == 0);
+        return FALSE;
+    }
+
+    nm_assert(NMP_OBJECT_GET_TYPE(obj_old) == NMP_OBJECT_GET_TYPE(needle));
+
+    switch (NMP_OBJECT_GET_TYPE(obj_old)) {
+    case NMP_OBJECT_TYPE_IP4_ADDRESS:
+        _notify_addresses(self);
+        break;
+    case NMP_OBJECT_TYPE_IP4_ROUTE:
+        if (priv->best_default_route == obj_old) {
+            if (nmp_object_ref_set(&priv->best_default_route,
+                                   _nm_ip4_config_best_default_route_find(self)))
+                _notify(self, PROP_GATEWAY);
+        }
+        _notify_routes(self);
+        break;
+    default:
+        nm_assert_not_reached();
+    }
+    return TRUE;
 }
 
 /*****************************************************************************/
 
 static void
-hash_u32 (GChecksum *sum, guint32 n)
+hash_u32(GChecksum *sum, guint32 n)
 {
-	g_checksum_update (sum, (const guint8 *) &n, sizeof (n));
+    g_checksum_update(sum, (const guint8 *) &n, sizeof(n));
 }
 
 void
-nm_ip4_config_hash (const NMIP4Config *self, GChecksum *sum, gboolean dns_only)
-{
-	guint i;
-	const char *s;
-	NMDedupMultiIter ipconf_iter;
-	const NMPlatformIP4Address *address;
-	const NMPlatformIP4Route *route;
-	int val;
-
-	g_return_if_fail (self);
-	g_return_if_fail (sum);
-
-	if (!dns_only) {
-		nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, self, &address) {
-			hash_u32 (sum, address->address);
-			hash_u32 (sum, address->plen);
-			hash_u32 (sum, address->peer_address & _nm_utils_ip4_prefix_to_netmask (address->plen));
-		}
-
-		nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, self, &route) {
-			hash_u32 (sum, route->network);
-			hash_u32 (sum, route->plen);
-			hash_u32 (sum, route->gateway);
-			hash_u32 (sum, route->metric);
-		}
-
-		for (i = 0; i < nm_ip4_config_get_num_nis_servers (self); i++)
-			hash_u32 (sum, nm_ip4_config_get_nis_server (self, i));
-
-		s = nm_ip4_config_get_nis_domain (self);
-		if (s)
-			g_checksum_update (sum, (const guint8 *) s, strlen (s));
-	}
-
-	for (i = 0; i < nm_ip4_config_get_num_nameservers (self); i++)
-		hash_u32 (sum, nm_ip4_config_get_nameserver (self, i));
-
-	for (i = 0; i < nm_ip4_config_get_num_wins (self); i++)
-		hash_u32 (sum, nm_ip4_config_get_wins (self, i));
-
-	for (i = 0; i < nm_ip4_config_get_num_domains (self); i++) {
-		s = nm_ip4_config_get_domain (self, i);
-		g_checksum_update (sum, (const guint8 *) s, strlen (s));
-	}
-
-	for (i = 0; i < nm_ip4_config_get_num_searches (self); i++) {
-		s = nm_ip4_config_get_search (self, i);
-		g_checksum_update (sum, (const guint8 *) s, strlen (s));
-	}
-
-	for (i = 0; i < nm_ip4_config_get_num_dns_options (self); i++) {
-		s = nm_ip4_config_get_dns_option (self, i);
-		g_checksum_update (sum, (const guint8 *) s, strlen (s));
-	}
-
-	val = nm_ip4_config_mdns_get (self);
-	if (val != NM_SETTING_CONNECTION_MDNS_DEFAULT)
-		g_checksum_update (sum, (const guint8 *) &val, sizeof (val));
-
-	val = nm_ip4_config_llmnr_get (self);
-	if (val != NM_SETTING_CONNECTION_LLMNR_DEFAULT)
-		g_checksum_update (sum, (const guint8 *) &val, sizeof (val));
-
-	/* FIXME(ip-config-checksum): the DNS priority should be considered relevant
-	 * and added into the checksum as well, but this can't be done right now
-	 * because in the DNS manager we rely on the fact that an empty
-	 * configuration (i.e. just created) has a zero checksum. This is needed to
-	 * avoid rewriting resolv.conf when there is no change.
-	 *
-	 * The DNS priority initial value depends on the connection type (VPN or
-	 * not), so it's a bit difficult to add it to checksum maintaining the
-	 * assumption of checksum(empty)=0
-	 */
+nm_ip4_config_hash(const NMIP4Config *self, GChecksum *sum, gboolean dns_only)
+{
+    guint                       i;
+    const char *                s;
+    NMDedupMultiIter            ipconf_iter;
+    const NMPlatformIP4Address *address;
+    const NMPlatformIP4Route *  route;
+    int                         val;
+
+    g_return_if_fail(self);
+    g_return_if_fail(sum);
+
+    if (!dns_only) {
+        nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, self, &address) {
+            hash_u32(sum, address->address);
+            hash_u32(sum, address->plen);
+            hash_u32(sum, address->peer_address & _nm_utils_ip4_prefix_to_netmask(address->plen));
+        }
+
+        nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, self, &route) {
+            hash_u32(sum, route->network);
+            hash_u32(sum, route->plen);
+            hash_u32(sum, route->gateway);
+            hash_u32(sum, route->metric);
+        }
+
+        for (i = 0; i < nm_ip4_config_get_num_nis_servers(self); i++)
+            hash_u32(sum, nm_ip4_config_get_nis_server(self, i));
+
+        s = nm_ip4_config_get_nis_domain(self);
+        if (s)
+            g_checksum_update(sum, (const guint8 *) s, strlen(s));
+    }
+
+    for (i = 0; i < nm_ip4_config_get_num_nameservers(self); i++)
+        hash_u32(sum, nm_ip4_config_get_nameserver(self, i));
+
+    for (i = 0; i < nm_ip4_config_get_num_wins(self); i++)
+        hash_u32(sum, nm_ip4_config_get_wins(self, i));
+
+    for (i = 0; i < nm_ip4_config_get_num_domains(self); i++) {
+        s = nm_ip4_config_get_domain(self, i);
+        g_checksum_update(sum, (const guint8 *) s, strlen(s));
+    }
+
+    for (i = 0; i < nm_ip4_config_get_num_searches(self); i++) {
+        s = nm_ip4_config_get_search(self, i);
+        g_checksum_update(sum, (const guint8 *) s, strlen(s));
+    }
+
+    for (i = 0; i < nm_ip4_config_get_num_dns_options(self); i++) {
+        s = nm_ip4_config_get_dns_option(self, i);
+        g_checksum_update(sum, (const guint8 *) s, strlen(s));
+    }
+
+    val = nm_ip4_config_mdns_get(self);
+    if (val != NM_SETTING_CONNECTION_MDNS_DEFAULT)
+        g_checksum_update(sum, (const guint8 *) &val, sizeof(val));
+
+    val = nm_ip4_config_llmnr_get(self);
+    if (val != NM_SETTING_CONNECTION_LLMNR_DEFAULT)
+        g_checksum_update(sum, (const guint8 *) &val, sizeof(val));
+
+    /* FIXME(ip-config-checksum): the DNS priority should be considered relevant
+     * and added into the checksum as well, but this can't be done right now
+     * because in the DNS manager we rely on the fact that an empty
+     * configuration (i.e. just created) has a zero checksum. This is needed to
+     * avoid rewriting resolv.conf when there is no change.
+     *
+     * The DNS priority initial value depends on the connection type (VPN or
+     * not), so it's a bit difficult to add it to checksum maintaining the
+     * assumption of checksum(empty)=0
+     */
 }
 
 /**
@@ -3100,465 +2902,385 @@ nm_ip4_config_hash (const NMIP4Config *self, GChecksum *sum, gboolean dns_only)
  * %FALSE if not
  */
 gboolean
-nm_ip4_config_equal (const NMIP4Config *a, const NMIP4Config *b)
+nm_ip4_config_equal(const NMIP4Config *a, const NMIP4Config *b)
 {
-	nm_auto_free_checksum GChecksum *a_checksum = g_checksum_new (G_CHECKSUM_SHA1);
-	nm_auto_free_checksum GChecksum *b_checksum = g_checksum_new (G_CHECKSUM_SHA1);
-	guint8 a_data[NM_UTILS_CHECKSUM_LENGTH_SHA1];
-	guint8 b_data[NM_UTILS_CHECKSUM_LENGTH_SHA1];
+    nm_auto_free_checksum GChecksum *a_checksum = g_checksum_new(G_CHECKSUM_SHA1);
+    nm_auto_free_checksum GChecksum *b_checksum = g_checksum_new(G_CHECKSUM_SHA1);
+    guint8                           a_data[NM_UTILS_CHECKSUM_LENGTH_SHA1];
+    guint8                           b_data[NM_UTILS_CHECKSUM_LENGTH_SHA1];
 
-	if (a)
-		nm_ip4_config_hash (a, a_checksum, FALSE);
-	if (b)
-		nm_ip4_config_hash (b, b_checksum, FALSE);
+    if (a)
+        nm_ip4_config_hash(a, a_checksum, FALSE);
+    if (b)
+        nm_ip4_config_hash(b, b_checksum, FALSE);
 
-	nm_utils_checksum_get_digest (a_checksum, a_data);
-	nm_utils_checksum_get_digest (b_checksum, b_data);
-	return !memcmp (a_data, b_data, sizeof (a_data));
+    nm_utils_checksum_get_digest(a_checksum, a_data);
+    nm_utils_checksum_get_digest(b_checksum, b_data);
+    return !memcmp(a_data, b_data, sizeof(a_data));
 }
 
 /*****************************************************************************/
 
 static void
-get_property (GObject *object, guint prop_id,
-              GValue *value, GParamSpec *pspec)
-{
-	NMIP4Config *self = NM_IP4_CONFIG (object);
-	NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
-	const NMDedupMultiHeadEntry *head_entry;
-	NMDedupMultiIter ipconf_iter;
-	const NMPlatformIP4Route *route;
-	GVariantBuilder builder_data, builder_legacy;
-	guint i;
-	char addr_str[NM_UTILS_INET_ADDRSTRLEN];
-
-	switch (prop_id) {
-	case PROP_IFINDEX:
-		g_value_set_int (value, priv->ifindex);
-		break;
-	case PROP_ADDRESS_DATA:
-	case PROP_ADDRESSES:
-		nm_assert (!!priv->address_data_variant == !!priv->addresses_variant);
-
-		if (priv->address_data_variant)
-			goto out_addresses_cached;
-
-		g_variant_builder_init (&builder_data, G_VARIANT_TYPE ("aa{sv}"));
-		g_variant_builder_init (&builder_legacy, G_VARIANT_TYPE ("aau"));
-
-		head_entry = nm_ip4_config_lookup_addresses (self);
-		if (head_entry) {
-			gs_free const NMPObject **addresses = NULL;
-			guint naddr;
-
-			addresses = (const NMPObject **) nm_dedup_multi_objs_to_array_head (head_entry, NULL, NULL, &naddr);
-			nm_assert (addresses && naddr);
-
-			g_qsort_with_data (addresses,
-			                   naddr,
-			                   sizeof (addresses[0]),
-			                   _addresses_sort_cmp,
-			                   NULL);
-
-			/* Build address data variant */
-			for (i = 0; i < naddr; i++) {
-				GVariantBuilder addr_builder;
-				const NMPlatformIP4Address *address = NMP_OBJECT_CAST_IP4_ADDRESS (addresses[i]);
-
-				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_inet4_ntop (address->address, addr_str)));
-				g_variant_builder_add (&addr_builder, "{sv}",
-				                       "prefix",
-				                       g_variant_new_uint32 (address->plen));
-				if (address->peer_address != address->address) {
-					g_variant_builder_add (&addr_builder, "{sv}",
-					                       "peer",
-					                       g_variant_new_string (_nm_utils_inet4_ntop (address->peer_address, addr_str)));
-				}
-
-				if (*address->label) {
-					g_variant_builder_add (&addr_builder, "{sv}",
-					                       NM_IP_ADDRESS_ATTRIBUTE_LABEL,
-					                       g_variant_new_string (address->label));
-				}
-
-				g_variant_builder_add (&builder_data, "a{sv}", &addr_builder);
-
-				{
-					const guint32 dbus_addr[3] = {
-					    address->address,
-					    address->plen,
-					    (   i == 0
-					     && priv->best_default_route)
-					       ? NMP_OBJECT_CAST_IP4_ROUTE (priv->best_default_route)->gateway
-					       : (guint32) 0,
-					};
-
-					g_variant_builder_add (&builder_legacy, "@au",
-					                       g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32,
-					                                                  dbus_addr, 3, sizeof (guint32)));
-				}
-			}
-		}
-
-		priv->address_data_variant = g_variant_ref_sink (g_variant_builder_end (&builder_data));
-		priv->addresses_variant = g_variant_ref_sink (g_variant_builder_end (&builder_legacy));
-
-out_addresses_cached:
-		g_value_set_variant (value,
-		                     prop_id == PROP_ADDRESS_DATA ?
-		                     priv->address_data_variant :
-		                     priv->addresses_variant);
-		break;
-	case PROP_ROUTE_DATA:
-	case PROP_ROUTES:
-		nm_assert (!!priv->route_data_variant == !!priv->routes_variant);
-
-		if (priv->route_data_variant)
-			goto out_routes_cached;
-
-		g_variant_builder_init (&builder_data, G_VARIANT_TYPE ("aa{sv}"));
-		g_variant_builder_init (&builder_legacy, G_VARIANT_TYPE ("aau"));
-
-		nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, self, &route) {
-			GVariantBuilder route_builder;
-
-			nm_assert (_route_valid (route));
-
-			if (route->type_coerced != nm_platform_route_type_coerce (RTN_UNICAST))
-				continue;
-
-			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_inet4_ntop (route->network, addr_str)));
-			g_variant_builder_add (&route_builder, "{sv}",
-			                       "prefix",
-			                       g_variant_new_uint32 (route->plen));
-			if (route->gateway) {
-				g_variant_builder_add (&route_builder, "{sv}",
-				                       "next-hop",
-				                       g_variant_new_string (_nm_utils_inet4_ntop (route->gateway, addr_str)));
-			}
-			g_variant_builder_add (&route_builder, "{sv}",
-			                       "metric",
-			                       g_variant_new_uint32 (route->metric));
-
-			if (!nm_platform_route_table_is_main (route->table_coerced)) {
-				g_variant_builder_add (&route_builder, "{sv}",
-				                       "table",
-				                       g_variant_new_uint32 (nm_platform_route_table_uncoerce (route->table_coerced, TRUE)));
-			}
-
-			g_variant_builder_add (&builder_data, "a{sv}", &route_builder);
-
-			/* legacy versions of nm_ip4_route_set_prefix() in libnm-util assert that the
-			 * plen is positive. Skip the default routes not to break older clients. */
-			if (   nm_platform_route_table_is_main (route->table_coerced)
-			    && !NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route)) {
-				const guint32 dbus_route[4] = {
-				    route->network,
-				    route->plen,
-				    route->gateway,
-				    route->metric,
-				};
-
-				g_variant_builder_add (&builder_legacy, "@au",
-				                       g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32,
-				                                                  dbus_route, 4, sizeof (guint32)));
-			}
-		}
-
-		priv->route_data_variant = g_variant_ref_sink (g_variant_builder_end (&builder_data));
-		priv->routes_variant = g_variant_ref_sink (g_variant_builder_end (&builder_legacy));
-
-out_routes_cached:
-		g_value_set_variant (value,
-		                     prop_id == PROP_ROUTE_DATA ?
-		                     priv->route_data_variant :
-		                     priv->routes_variant);
-		break;
-	case PROP_GATEWAY:
-		if (priv->best_default_route) {
-			g_value_take_string (value,
-			                    nm_utils_inet4_ntop_dup (NMP_OBJECT_CAST_IP4_ROUTE (priv->best_default_route)->gateway));
-		} else
-			g_value_set_string (value, NULL);
-		break;
-	case PROP_NAMESERVER_DATA:
-		g_variant_builder_init (&builder_data, G_VARIANT_TYPE ("aa{sv}"));
-
-		for (i = 0; i < priv->nameservers->len; i++) {
-			GVariantBuilder nested_builder;
-
-			_nm_utils_inet4_ntop (g_array_index (priv->nameservers, in_addr_t, i),
-			                      addr_str);
-
-			g_variant_builder_init (&nested_builder, G_VARIANT_TYPE ("a{sv}"));
-			g_variant_builder_add (&nested_builder, "{sv}",
-			                       "address",
-			                       g_variant_new_string (addr_str));
-			g_variant_builder_add (&builder_data, "a{sv}", &nested_builder);
-		}
-
-		g_value_take_variant (value,
-		                      g_variant_builder_end (&builder_data));
-		break;
-	case PROP_NAMESERVERS:
-		g_value_take_variant (value,
-		                      g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32,
-		                                                 priv->nameservers->data,
-		                                                 priv->nameservers->len,
-		                                                 sizeof (guint32)));
-		break;
-	case PROP_DOMAINS:
-		nm_utils_g_value_set_strv (value, priv->domains);
-		break;
-	case PROP_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;
-	case PROP_DNS_PRIORITY:
-		g_value_set_int (value, priv->dns_priority);
-		break;
-	case PROP_WINS_SERVER_DATA:
-		g_variant_builder_init (&builder_data, G_VARIANT_TYPE ("as"));
-		for (i = 0; i < priv->wins->len; i++) {
-			g_variant_builder_add (&builder_data,
-			                       "s",
-			                       _nm_utils_inet4_ntop (g_array_index (priv->wins, in_addr_t, i),
-			                                             addr_str));
-		}
-		g_value_take_variant (value,
-		                      g_variant_builder_end (&builder_data));
-		break;
-	case PROP_WINS_SERVERS:
-		g_value_take_variant (value,
-		                      g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32,
-		                                                 priv->wins->data,
-		                                                 priv->wins->len,
-		                                                 sizeof (guint32)));
-		break;
-	default:
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-		break;
-	}
+get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+    NMIP4Config *       self = NM_IP4_CONFIG(object);
+    NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
+    char                addr_str[NM_UTILS_INET_ADDRSTRLEN];
+    GVariantBuilder     builder_data;
+    guint               i;
+
+    switch (prop_id) {
+    case PROP_IFINDEX:
+        g_value_set_int(value, priv->ifindex);
+        break;
+    case PROP_ADDRESS_DATA:
+    case PROP_ADDRESSES:
+        nm_assert(!!priv->address_data_variant == !!priv->addresses_variant);
+
+        if (!priv->address_data_variant) {
+            nm_utils_ip_addresses_to_dbus(AF_INET,
+                                          nm_ip4_config_lookup_addresses(self),
+                                          priv->best_default_route,
+                                          NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN,
+                                          &priv->address_data_variant,
+                                          &priv->addresses_variant);
+            g_variant_ref_sink(priv->address_data_variant);
+            g_variant_ref_sink(priv->addresses_variant);
+        }
+
+        g_value_set_variant(value,
+                            prop_id == PROP_ADDRESS_DATA ? priv->address_data_variant
+                                                         : priv->addresses_variant);
+        break;
+    case PROP_ROUTE_DATA:
+    case PROP_ROUTES:
+        nm_assert(!!priv->route_data_variant == !!priv->routes_variant);
+
+        if (!priv->route_data_variant) {
+            nm_utils_ip_routes_to_dbus(AF_INET,
+                                       nm_ip4_config_lookup_routes(self),
+                                       &priv->route_data_variant,
+                                       &priv->routes_variant);
+            g_variant_ref_sink(priv->route_data_variant);
+            g_variant_ref_sink(priv->routes_variant);
+        }
+
+        g_value_set_variant(value,
+                            prop_id == PROP_ROUTE_DATA ? priv->route_data_variant
+                                                       : priv->routes_variant);
+        break;
+    case PROP_GATEWAY:
+        if (priv->best_default_route) {
+            g_value_take_string(value,
+                                nm_utils_inet4_ntop_dup(
+                                    NMP_OBJECT_CAST_IP4_ROUTE(priv->best_default_route)->gateway));
+        } else
+            g_value_set_string(value, NULL);
+        break;
+    case PROP_NAMESERVER_DATA:
+        g_variant_builder_init(&builder_data, G_VARIANT_TYPE("aa{sv}"));
+
+        for (i = 0; i < priv->nameservers->len; i++) {
+            GVariantBuilder nested_builder;
+
+            _nm_utils_inet4_ntop(g_array_index(priv->nameservers, in_addr_t, i), addr_str);
+
+            g_variant_builder_init(&nested_builder, G_VARIANT_TYPE("a{sv}"));
+            g_variant_builder_add(&nested_builder,
+                                  "{sv}",
+                                  "address",
+                                  g_variant_new_string(addr_str));
+            g_variant_builder_add(&builder_data, "a{sv}", &nested_builder);
+        }
+
+        g_value_take_variant(value, g_variant_builder_end(&builder_data));
+        break;
+    case PROP_NAMESERVERS:
+        g_value_take_variant(value,
+                             g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
+                                                       priv->nameservers->data,
+                                                       priv->nameservers->len,
+                                                       sizeof(guint32)));
+        break;
+    case PROP_DOMAINS:
+        nm_utils_g_value_set_strv(value, priv->domains);
+        break;
+    case PROP_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;
+    case PROP_DNS_PRIORITY:
+        g_value_set_int(value, priv->dns_priority);
+        break;
+    case PROP_WINS_SERVER_DATA:
+        g_variant_builder_init(&builder_data, G_VARIANT_TYPE("as"));
+        for (i = 0; i < priv->wins->len; i++) {
+            g_variant_builder_add(
+                &builder_data,
+                "s",
+                _nm_utils_inet4_ntop(g_array_index(priv->wins, in_addr_t, i), addr_str));
+        }
+        g_value_take_variant(value, g_variant_builder_end(&builder_data));
+        break;
+    case PROP_WINS_SERVERS:
+        g_value_take_variant(value,
+                             g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
+                                                       priv->wins->data,
+                                                       priv->wins->len,
+                                                       sizeof(guint32)));
+        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)
-{
-	NMIP4Config *self = NM_IP4_CONFIG (object);
-	NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
-
-	switch (prop_id) {
-	case PROP_MULTI_IDX:
-		/* construct-only */
-		priv->multi_idx = g_value_get_pointer (value);
-		if (!priv->multi_idx)
-			g_return_if_reached ();
-		nm_dedup_multi_index_ref (priv->multi_idx);
-		break;
-	case PROP_IFINDEX:
-		/* construct-only */
-		priv->ifindex = g_value_get_int (value);
-		break;
-	default:
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-		break;
-	}
+set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+    NMIP4Config *       self = NM_IP4_CONFIG(object);
+    NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
+
+    switch (prop_id) {
+    case PROP_MULTI_IDX:
+        /* construct-only */
+        priv->multi_idx = g_value_get_pointer(value);
+        if (!priv->multi_idx)
+            g_return_if_reached();
+        nm_dedup_multi_index_ref(priv->multi_idx);
+        break;
+    case PROP_IFINDEX:
+        /* construct-only */
+        priv->ifindex = g_value_get_int(value);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
 }
 
 /*****************************************************************************/
 
 static void
-nm_ip4_config_init (NMIP4Config *self)
+nm_ip4_config_init(NMIP4Config *self)
 {
-	NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+    NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
 
-	nm_ip_config_dedup_multi_idx_type_init ((NMIPConfigDedupMultiIdxType *) &priv->idx_ip4_addresses,
-	                                        NMP_OBJECT_TYPE_IP4_ADDRESS);
-	nm_ip_config_dedup_multi_idx_type_init ((NMIPConfigDedupMultiIdxType *) &priv->idx_ip4_routes,
-	                                        NMP_OBJECT_TYPE_IP4_ROUTE);
+    nm_ip_config_dedup_multi_idx_type_init((NMIPConfigDedupMultiIdxType *) &priv->idx_ip4_addresses,
+                                           NMP_OBJECT_TYPE_IP4_ADDRESS);
+    nm_ip_config_dedup_multi_idx_type_init((NMIPConfigDedupMultiIdxType *) &priv->idx_ip4_routes,
+                                           NMP_OBJECT_TYPE_IP4_ROUTE);
 
-	priv->mdns = NM_SETTING_CONNECTION_MDNS_DEFAULT;
-	priv->llmnr = NM_SETTING_CONNECTION_LLMNR_DEFAULT;
-	priv->nameservers = g_array_new (FALSE, FALSE, sizeof (guint32));
-	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->nis = g_array_new (FALSE, TRUE, sizeof (guint32));
-	priv->wins = g_array_new (FALSE, TRUE, sizeof (guint32));
+    priv->mdns        = NM_SETTING_CONNECTION_MDNS_DEFAULT;
+    priv->llmnr       = NM_SETTING_CONNECTION_LLMNR_DEFAULT;
+    priv->nameservers = g_array_new(FALSE, FALSE, sizeof(guint32));
+    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->nis         = g_array_new(FALSE, TRUE, sizeof(guint32));
+    priv->wins        = g_array_new(FALSE, TRUE, sizeof(guint32));
 }
 
 NMIP4Config *
-nm_ip4_config_new (NMDedupMultiIndex *multi_idx, int ifindex)
+nm_ip4_config_new(NMDedupMultiIndex *multi_idx, int ifindex)
 {
-	g_return_val_if_fail (ifindex >= -1, NULL);
-	return (NMIP4Config *) g_object_new (NM_TYPE_IP4_CONFIG,
-	                                     NM_IP4_CONFIG_MULTI_IDX, multi_idx,
-	                                     NM_IP4_CONFIG_IFINDEX, ifindex,
-	                                     NULL);
+    g_return_val_if_fail(ifindex >= -1, NULL);
+    return (NMIP4Config *) g_object_new(NM_TYPE_IP4_CONFIG,
+                                        NM_IP4_CONFIG_MULTI_IDX,
+                                        multi_idx,
+                                        NM_IP4_CONFIG_IFINDEX,
+                                        ifindex,
+                                        NULL);
 }
 
 static void
-finalize (GObject *object)
+finalize(GObject *object)
 {
-	NMIP4Config *self = NM_IP4_CONFIG (object);
-	NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
+    NMIP4Config *       self = NM_IP4_CONFIG(object);
+    NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
 
-	nm_clear_nmp_object (&priv->best_default_route);
+    nm_clear_nmp_object(&priv->best_default_route);
 
-	nm_dedup_multi_index_remove_idx (priv->multi_idx, &priv->idx_ip4_addresses);
-	nm_dedup_multi_index_remove_idx (priv->multi_idx, &priv->idx_ip4_routes);
+    nm_dedup_multi_index_remove_idx(priv->multi_idx, &priv->idx_ip4_addresses);
+    nm_dedup_multi_index_remove_idx(priv->multi_idx, &priv->idx_ip4_routes);
 
-	nm_clear_g_variant (&priv->address_data_variant);
-	nm_clear_g_variant (&priv->addresses_variant);
-	nm_clear_g_variant (&priv->route_data_variant);
-	nm_clear_g_variant (&priv->routes_variant);
+    nm_clear_g_variant(&priv->address_data_variant);
+    nm_clear_g_variant(&priv->addresses_variant);
+    nm_clear_g_variant(&priv->route_data_variant);
+    nm_clear_g_variant(&priv->routes_variant);
 
-	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_array_unref (priv->nis);
-	g_free (priv->nis_domain);
-	g_array_unref (priv->wins);
+    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_array_unref(priv->nis);
+    g_free(priv->nis_domain);
+    g_array_unref(priv->wins);
 
-	G_OBJECT_CLASS (nm_ip4_config_parent_class)->finalize (object);
+    G_OBJECT_CLASS(nm_ip4_config_parent_class)->finalize(object);
 
-	nm_dedup_multi_index_unref (priv->multi_idx);
+    nm_dedup_multi_index_unref(priv->multi_idx);
 }
 
 static const NMDBusInterfaceInfoExtended interface_info_ip4_config = {
-	.parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT (
-		NM_DBUS_INTERFACE_IP4_CONFIG,
-		.signals = NM_DEFINE_GDBUS_SIGNAL_INFOS (
-			&nm_signal_info_property_changed_legacy,
-		),
-		.properties = NM_DEFINE_GDBUS_PROPERTY_INFOS (
-			NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Addresses",      "aau",    NM_IP4_CONFIG_ADDRESSES),
-			NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("AddressData",    "aa{sv}", NM_IP4_CONFIG_ADDRESS_DATA),
-			NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Gateway",        "s",      NM_IP4_CONFIG_GATEWAY),
-			NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Routes",         "aau",    NM_IP4_CONFIG_ROUTES),
-			NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("RouteData",      "aa{sv}", NM_IP4_CONFIG_ROUTE_DATA),
-			NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE   ("NameserverData", "aa{sv}", NM_IP4_CONFIG_NAMESERVER_DATA),
-			NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Nameservers",    "au",     NM_IP4_CONFIG_NAMESERVERS),
-			NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Domains",        "as",     NM_IP4_CONFIG_DOMAINS),
-			NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Searches",       "as",     NM_IP4_CONFIG_SEARCHES),
-			NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("DnsOptions",     "as",     NM_IP4_CONFIG_DNS_OPTIONS),
-			NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("DnsPriority",    "i",      NM_IP4_CONFIG_DNS_PRIORITY),
-			NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE   ("WinsServerData", "as",     NM_IP4_CONFIG_WINS_SERVER_DATA),
-			NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("WinsServers",    "au",     NM_IP4_CONFIG_WINS_SERVERS),
-		),
-	),
-	.legacy_property_changed = TRUE,
+    .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT(
+        NM_DBUS_INTERFACE_IP4_CONFIG,
+        .signals    = NM_DEFINE_GDBUS_SIGNAL_INFOS(&nm_signal_info_property_changed_legacy, ),
+        .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS(
+            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Addresses",
+                                                             "aau",
+                                                             NM_IP4_CONFIG_ADDRESSES),
+            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("AddressData",
+                                                             "aa{sv}",
+                                                             NM_IP4_CONFIG_ADDRESS_DATA),
+            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Gateway", "s", NM_IP4_CONFIG_GATEWAY),
+            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Routes", "aau", NM_IP4_CONFIG_ROUTES),
+            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("RouteData",
+                                                             "aa{sv}",
+                                                             NM_IP4_CONFIG_ROUTE_DATA),
+            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("NameserverData",
+                                                           "aa{sv}",
+                                                           NM_IP4_CONFIG_NAMESERVER_DATA),
+            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Nameservers",
+                                                             "au",
+                                                             NM_IP4_CONFIG_NAMESERVERS),
+            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Domains",
+                                                             "as",
+                                                             NM_IP4_CONFIG_DOMAINS),
+            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Searches",
+                                                             "as",
+                                                             NM_IP4_CONFIG_SEARCHES),
+            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("DnsOptions",
+                                                             "as",
+                                                             NM_IP4_CONFIG_DNS_OPTIONS),
+            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("DnsPriority",
+                                                             "i",
+                                                             NM_IP4_CONFIG_DNS_PRIORITY),
+            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("WinsServerData",
+                                                           "as",
+                                                           NM_IP4_CONFIG_WINS_SERVER_DATA),
+            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("WinsServers",
+                                                             "au",
+                                                             NM_IP4_CONFIG_WINS_SERVERS), ), ),
+    .legacy_property_changed = TRUE,
 };
 
 static void
-nm_ip4_config_class_init (NMIP4ConfigClass *config_class)
-{
-	GObjectClass *object_class = G_OBJECT_CLASS (config_class);
-	NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (config_class);
-
-	dbus_object_class->export_path = NM_DBUS_EXPORT_PATH_NUMBERED (NM_DBUS_PATH"/IP4Config");
-	dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_ip4_config);
-
-	object_class->get_property = get_property;
-	object_class->set_property = set_property;
-	object_class->finalize = finalize;
-
-	obj_properties[PROP_MULTI_IDX] =
-	    g_param_spec_pointer (NM_IP4_CONFIG_MULTI_IDX, "", "",
-	                            G_PARAM_WRITABLE
-	                          | G_PARAM_CONSTRUCT_ONLY
-	                          | G_PARAM_STATIC_STRINGS);
-	obj_properties[PROP_IFINDEX] =
-	    g_param_spec_int (NM_IP4_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_variant (NM_IP4_CONFIG_ADDRESS_DATA, "", "",
-	                          G_VARIANT_TYPE ("aa{sv}"),
-	                          NULL,
-	                          G_PARAM_READABLE |
-	                          G_PARAM_STATIC_STRINGS);
-	obj_properties[PROP_ADDRESSES] =
-	    g_param_spec_variant (NM_IP4_CONFIG_ADDRESSES, "", "",
-	                          G_VARIANT_TYPE ("aau"),
-	                          NULL,
-	                          G_PARAM_READABLE |
-	                          G_PARAM_STATIC_STRINGS);
-	obj_properties[PROP_ROUTE_DATA] =
-	    g_param_spec_variant (NM_IP4_CONFIG_ROUTE_DATA, "", "",
-	                          G_VARIANT_TYPE ("aa{sv}"),
-	                          NULL,
-	                          G_PARAM_READABLE |
-	                          G_PARAM_STATIC_STRINGS);
-	obj_properties[PROP_ROUTES] =
-	    g_param_spec_variant (NM_IP4_CONFIG_ROUTES, "", "",
-	                          G_VARIANT_TYPE ("aau"),
-	                          NULL,
-	                          G_PARAM_READABLE |
-	                          G_PARAM_STATIC_STRINGS);
-	obj_properties[PROP_GATEWAY] =
-	    g_param_spec_string (NM_IP4_CONFIG_GATEWAY, "", "",
-	                         NULL,
-	                         G_PARAM_READABLE |
-	                         G_PARAM_STATIC_STRINGS);
-	obj_properties[PROP_NAMESERVER_DATA] =
-	    g_param_spec_variant (NM_IP4_CONFIG_NAMESERVER_DATA, "", "",
-	                          G_VARIANT_TYPE ("aa{sv}"),
-	                          NULL,
-	                          G_PARAM_READABLE |
-	                          G_PARAM_STATIC_STRINGS);
-	obj_properties[PROP_NAMESERVERS] =
-	    g_param_spec_variant (NM_IP4_CONFIG_NAMESERVERS, "", "",
-	                          G_VARIANT_TYPE ("au"),
-	                          NULL,
-	                          G_PARAM_READABLE |
-	                          G_PARAM_STATIC_STRINGS);
-	obj_properties[PROP_DOMAINS] =
-	    g_param_spec_boxed (NM_IP4_CONFIG_DOMAINS, "", "",
-	                        G_TYPE_STRV,
-	                        G_PARAM_READABLE |
-	                        G_PARAM_STATIC_STRINGS);
-	obj_properties[PROP_SEARCHES] =
-	    g_param_spec_boxed (NM_IP4_CONFIG_SEARCHES, "", "",
-	                        G_TYPE_STRV,
-	                        G_PARAM_READABLE |
-	                        G_PARAM_STATIC_STRINGS);
-	obj_properties[PROP_DNS_OPTIONS] =
-	     g_param_spec_boxed (NM_IP4_CONFIG_DNS_OPTIONS, "", "",
-	                         G_TYPE_STRV,
-	                         G_PARAM_READABLE |
-	                         G_PARAM_STATIC_STRINGS);
-	obj_properties[PROP_DNS_PRIORITY] =
-	     g_param_spec_int (NM_IP4_CONFIG_DNS_PRIORITY, "", "",
-	                       G_MININT32, G_MAXINT32, 0,
-	                       G_PARAM_READABLE |
-	                       G_PARAM_STATIC_STRINGS);
-	obj_properties[PROP_WINS_SERVER_DATA] =
-	    g_param_spec_variant (NM_IP4_CONFIG_WINS_SERVER_DATA, "", "",
-	                          G_VARIANT_TYPE ("as"),
-	                          NULL,
-	                          G_PARAM_READABLE |
-	                          G_PARAM_STATIC_STRINGS);
-	obj_properties[PROP_WINS_SERVERS] =
-	    g_param_spec_variant (NM_IP4_CONFIG_WINS_SERVERS, "", "",
-	                          G_VARIANT_TYPE ("au"),
-	                          NULL,
-	                          G_PARAM_READABLE |
-	                          G_PARAM_STATIC_STRINGS);
-
-	g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
+nm_ip4_config_class_init(NMIP4ConfigClass *klass)
+{
+    GObjectClass *     object_class      = G_OBJECT_CLASS(klass);
+    NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass);
+    NMIPConfigClass *  ip_config_class   = NM_IP_CONFIG_CLASS(klass);
+
+    ip_config_class->is_ipv4     = TRUE;
+    ip_config_class->addr_family = AF_INET;
+
+    dbus_object_class->export_path     = NM_DBUS_EXPORT_PATH_NUMBERED(NM_DBUS_PATH "/IP4Config");
+    dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS(&interface_info_ip4_config);
+
+    object_class->get_property = get_property;
+    object_class->set_property = set_property;
+    object_class->finalize     = finalize;
+
+    obj_properties[PROP_MULTI_IDX] =
+        g_param_spec_pointer(NM_IP4_CONFIG_MULTI_IDX,
+                             "",
+                             "",
+                             G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+    obj_properties[PROP_IFINDEX] =
+        g_param_spec_int(NM_IP4_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_variant(NM_IP4_CONFIG_ADDRESS_DATA,
+                             "",
+                             "",
+                             G_VARIANT_TYPE("aa{sv}"),
+                             NULL,
+                             G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+    obj_properties[PROP_ADDRESSES] =
+        g_param_spec_variant(NM_IP4_CONFIG_ADDRESSES,
+                             "",
+                             "",
+                             G_VARIANT_TYPE("aau"),
+                             NULL,
+                             G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+    obj_properties[PROP_ROUTE_DATA] =
+        g_param_spec_variant(NM_IP4_CONFIG_ROUTE_DATA,
+                             "",
+                             "",
+                             G_VARIANT_TYPE("aa{sv}"),
+                             NULL,
+                             G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+    obj_properties[PROP_ROUTES]  = g_param_spec_variant(NM_IP4_CONFIG_ROUTES,
+                                                       "",
+                                                       "",
+                                                       G_VARIANT_TYPE("aau"),
+                                                       NULL,
+                                                       G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+    obj_properties[PROP_GATEWAY] = g_param_spec_string(NM_IP4_CONFIG_GATEWAY,
+                                                       "",
+                                                       "",
+                                                       NULL,
+                                                       G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+    obj_properties[PROP_NAMESERVER_DATA] =
+        g_param_spec_variant(NM_IP4_CONFIG_NAMESERVER_DATA,
+                             "",
+                             "",
+                             G_VARIANT_TYPE("aa{sv}"),
+                             NULL,
+                             G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+    obj_properties[PROP_NAMESERVERS] =
+        g_param_spec_variant(NM_IP4_CONFIG_NAMESERVERS,
+                             "",
+                             "",
+                             G_VARIANT_TYPE("au"),
+                             NULL,
+                             G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+    obj_properties[PROP_DOMAINS]  = g_param_spec_boxed(NM_IP4_CONFIG_DOMAINS,
+                                                      "",
+                                                      "",
+                                                      G_TYPE_STRV,
+                                                      G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+    obj_properties[PROP_SEARCHES] = g_param_spec_boxed(NM_IP4_CONFIG_SEARCHES,
+                                                       "",
+                                                       "",
+                                                       G_TYPE_STRV,
+                                                       G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+    obj_properties[PROP_DNS_OPTIONS] =
+        g_param_spec_boxed(NM_IP4_CONFIG_DNS_OPTIONS,
+                           "",
+                           "",
+                           G_TYPE_STRV,
+                           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+    obj_properties[PROP_DNS_PRIORITY] = g_param_spec_int(NM_IP4_CONFIG_DNS_PRIORITY,
+                                                         "",
+                                                         "",
+                                                         G_MININT32,
+                                                         G_MAXINT32,
+                                                         0,
+                                                         G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+    obj_properties[PROP_WINS_SERVER_DATA] =
+        g_param_spec_variant(NM_IP4_CONFIG_WINS_SERVER_DATA,
+                             "",
+                             "",
+                             G_VARIANT_TYPE("as"),
+                             NULL,
+                             G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+    obj_properties[PROP_WINS_SERVERS] =
+        g_param_spec_variant(NM_IP4_CONFIG_WINS_SERVERS,
+                             "",
+                             "",
+                             G_VARIANT_TYPE("au"),
+                             NULL,
+                             G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+    g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties);
 }