summary refs log tree commit diff
path: root/src/platform/nmp-rules-manager.c
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2020-10-05 22:27:18 +0200
committerMichael Biebl <biebl@debian.org>2020-10-05 22:27:18 +0200
commitaafc1dbe4712c86189bbc1d4d54ad8cb4c69be7e (patch)
treea2a9bb4d007339a0b1304540388230ccedac32bd /src/platform/nmp-rules-manager.c
parente7b44ef4c80907346ec7492a09c45277459924fc (diff)
New upstream version 1.27.90 upstream/1.27.90
Diffstat (limited to 'src/platform/nmp-rules-manager.c')
-rw-r--r--src/platform/nmp-rules-manager.c1204
1 files changed, 606 insertions, 598 deletions
diff --git a/src/platform/nmp-rules-manager.c b/src/platform/nmp-rules-manager.c
index a1d724c5..d139c9a3 100644
--- a/src/platform/nmp-rules-manager.c
+++ b/src/platform/nmp-rules-manager.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: LGPL-2.1+
+/* SPDX-License-Identifier: LGPL-2.1+ */
 
 #include "nm-default.h"
 
@@ -13,276 +13,278 @@
 /*****************************************************************************/
 
 struct _NMPRulesManager {
-	NMPlatform *platform;
-	GHashTable *by_obj;
-	GHashTable *by_user_tag;
-	GHashTable *by_data;
-	guint ref_count;
+    NMPlatform *platform;
+    GHashTable *by_obj;
+    GHashTable *by_user_tag;
+    GHashTable *by_data;
+    guint       ref_count;
 };
 
 /*****************************************************************************/
 
-static void _rules_init (NMPRulesManager *self);
+static void _rules_init(NMPRulesManager *self);
 
 /*****************************************************************************/
 
-#define _NMLOG_DOMAIN           LOGD_PLATFORM
-#define _NMLOG_PREFIX_NAME      "rules-manager"
-
-#define _NMLOG(level, ...) \
-    G_STMT_START { \
-        const NMLogLevel __level = (level); \
-        \
-        if (nm_logging_enabled (__level, _NMLOG_DOMAIN)) { \
-            _nm_log (__level, _NMLOG_DOMAIN, 0, NULL, NULL, \
-                     "%s: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \
-                     _NMLOG_PREFIX_NAME \
-                     _NM_UTILS_MACRO_REST (__VA_ARGS__)); \
-        } \
-    } G_STMT_END
+#define _NMLOG_DOMAIN      LOGD_PLATFORM
+#define _NMLOG_PREFIX_NAME "rules-manager"
+
+#define _NMLOG(level, ...)                                                 \
+    G_STMT_START                                                           \
+    {                                                                      \
+        const NMLogLevel __level = (level);                                \
+                                                                           \
+        if (nm_logging_enabled(__level, _NMLOG_DOMAIN)) {                  \
+            _nm_log(__level,                                               \
+                    _NMLOG_DOMAIN,                                         \
+                    0,                                                     \
+                    NULL,                                                  \
+                    NULL,                                                  \
+                    "%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__),             \
+                    _NMLOG_PREFIX_NAME _NM_UTILS_MACRO_REST(__VA_ARGS__)); \
+        }                                                                  \
+    }                                                                      \
+    G_STMT_END
 
 /*****************************************************************************/
 
 static gboolean
-NMP_IS_RULES_MANAGER (gpointer self)
+NMP_IS_RULES_MANAGER(gpointer self)
 {
-	return    self
-	       && ((NMPRulesManager *) self)->ref_count > 0
-	       && NM_IS_PLATFORM (((NMPRulesManager *) self)->platform);
+    return self && ((NMPRulesManager *) self)->ref_count > 0
+           && NM_IS_PLATFORM(((NMPRulesManager *) self)->platform);
 }
 
-#define _USER_TAG_LOG(user_tag) nm_hash_obfuscate_ptr (1240261787u, (user_tag))
+#define _USER_TAG_LOG(user_tag) nm_hash_obfuscate_ptr(1240261787u, (user_tag))
 
 /*****************************************************************************/
 
 typedef struct {
-	const NMPObject *obj;
-	gconstpointer user_tag;
-	CList obj_lst;
-	CList user_tag_lst;
-
-	/* track_priority_val zero is special: those are weakly tracked rules.
-	 * That means: NetworkManager will restore them only if it removed them earlier.
-	 * But it will not remove or add them otherwise.
-	 *
-	 * Otherwise, the track_priority_val goes together with track_priority_present.
-	 * In case of one rule being tracked multiple times (with different priorities),
-	 * the one with higher priority wins. See _rules_obj_get_best_data().
-	 * Then, the winning present state either enforces that the rule is present
-	 * or absent.
-	 *
-	 * If a rules is not tracked at all, it is ignored by NetworkManager. Assuming
-	 * that it was added externally by the user. But unlike weakly tracked rules,
-	 * NM will *not* restore such rules if NetworkManager themself removed them. */
-	guint32 track_priority_val;
-	bool track_priority_present:1;
-
-	bool dirty:1;
+    const NMPObject *obj;
+    gconstpointer    user_tag;
+    CList            obj_lst;
+    CList            user_tag_lst;
+
+    /* track_priority_val zero is special: those are weakly tracked rules.
+     * That means: NetworkManager will restore them only if it removed them earlier.
+     * But it will not remove or add them otherwise.
+     *
+     * Otherwise, the track_priority_val goes together with track_priority_present.
+     * In case of one rule being tracked multiple times (with different priorities),
+     * the one with higher priority wins. See _rules_obj_get_best_data().
+     * Then, the winning present state either enforces that the rule is present
+     * or absent.
+     *
+     * If a rules is not tracked at all, it is ignored by NetworkManager. Assuming
+     * that it was added externally by the user. But unlike weakly tracked rules,
+     * NM will *not* restore such rules if NetworkManager themself removed them. */
+    guint32 track_priority_val;
+    bool    track_priority_present : 1;
+
+    bool dirty : 1;
 } RulesData;
 
 typedef enum {
-	CONFIG_STATE_NONE          = 0,
-	CONFIG_STATE_ADDED_BY_US   = 1,
-	CONFIG_STATE_REMOVED_BY_US = 2,
-
-	/* ConfigState encodes whether the rule was touched by us at all (CONFIG_STATE_NONE).
-	 *
-	 * Maybe we would only need to track whether we touched the rule at all. But we
-	 * track it more in detail what we did: did we add it (CONFIG_STATE_ADDED_BY_US)
-	 * or did we remove it (CONFIG_STATE_REMOVED_BY_US)?
-	 * Finally, we need CONFIG_STATE_OWNED_BY_US, which means that we didn't actively
-	 * add/remove it, but whenever we are about to undo the add/remove, we need to do it.
-	 * In that sense, CONFIG_STATE_OWNED_BY_US is really just a flag that we unconditionally
-	 * force the state next time when necessary. */
-	CONFIG_STATE_OWNED_BY_US   = 3,
+    CONFIG_STATE_NONE          = 0,
+    CONFIG_STATE_ADDED_BY_US   = 1,
+    CONFIG_STATE_REMOVED_BY_US = 2,
+
+    /* ConfigState encodes whether the rule was touched by us at all (CONFIG_STATE_NONE).
+     *
+     * Maybe we would only need to track whether we touched the rule at all. But we
+     * track it more in detail what we did: did we add it (CONFIG_STATE_ADDED_BY_US)
+     * or did we remove it (CONFIG_STATE_REMOVED_BY_US)?
+     * Finally, we need CONFIG_STATE_OWNED_BY_US, which means that we didn't actively
+     * add/remove it, but whenever we are about to undo the add/remove, we need to do it.
+     * In that sense, CONFIG_STATE_OWNED_BY_US is really just a flag that we unconditionally
+     * force the state next time when necessary. */
+    CONFIG_STATE_OWNED_BY_US = 3,
 } ConfigState;
 
 typedef struct {
-	const NMPObject *obj;
-	CList obj_lst_head;
-
-	/* indicates whether we configured/removed the rule (during sync()). We need that, so
-	 * if the rule gets untracked, that we know to remove/restore it.
-	 *
-	 * This makes NMPRulesManager stateful (beyond the configuration that indicates
-	 * which rules are tracked).
-	 * After a restart, NetworkManager would no longer remember which rules were added
-	 * by us.
-	 *
-	 * That is partially fixed by NetworkManager taking over the rules that it
-	 * actively configures (see %NMP_RULES_MANAGER_EXTERN_WEAKLY_TRACKED_USER_TAG). */
-	ConfigState config_state;
+    const NMPObject *obj;
+    CList            obj_lst_head;
+
+    /* indicates whether we configured/removed the rule (during sync()). We need that, so
+     * if the rule gets untracked, that we know to remove/restore it.
+     *
+     * This makes NMPRulesManager stateful (beyond the configuration that indicates
+     * which rules are tracked).
+     * After a restart, NetworkManager would no longer remember which rules were added
+     * by us.
+     *
+     * That is partially fixed by NetworkManager taking over the rules that it
+     * actively configures (see %NMP_RULES_MANAGER_EXTERN_WEAKLY_TRACKED_USER_TAG). */
+    ConfigState config_state;
 } RulesObjData;
 
 typedef struct {
-	gconstpointer user_tag;
-	CList user_tag_lst_head;
+    gconstpointer user_tag;
+    CList         user_tag_lst_head;
 } RulesUserTagData;
 
 /*****************************************************************************/
 
-static void _rules_data_untrack (NMPRulesManager *self,
-                                 RulesData *rules_data,
-                                 gboolean remove_user_tag_data,
-                                 gboolean make_owned_by_us);
+static void _rules_data_untrack(NMPRulesManager *self,
+                                RulesData *      rules_data,
+                                gboolean         remove_user_tag_data,
+                                gboolean         make_owned_by_us);
 
 /*****************************************************************************/
 
 static void
-_rules_data_assert (const RulesData *rules_data, gboolean linked)
+_rules_data_assert(const RulesData *rules_data, gboolean linked)
 {
-	nm_assert (rules_data);
-	nm_assert (NMP_OBJECT_GET_TYPE (rules_data->obj) == NMP_OBJECT_TYPE_ROUTING_RULE);
-	nm_assert (nmp_object_is_visible (rules_data->obj));
-	nm_assert (rules_data->user_tag);
-	nm_assert (!linked || !c_list_is_empty (&rules_data->obj_lst));
-	nm_assert (!linked || !c_list_is_empty (&rules_data->user_tag_lst));
+    nm_assert(rules_data);
+    nm_assert(NMP_OBJECT_GET_TYPE(rules_data->obj) == NMP_OBJECT_TYPE_ROUTING_RULE);
+    nm_assert(nmp_object_is_visible(rules_data->obj));
+    nm_assert(rules_data->user_tag);
+    nm_assert(!linked || !c_list_is_empty(&rules_data->obj_lst));
+    nm_assert(!linked || !c_list_is_empty(&rules_data->user_tag_lst));
 }
 
 static guint
-_rules_data_hash (gconstpointer data)
+_rules_data_hash(gconstpointer data)
 {
-	const RulesData *rules_data = data;
-	NMHashState h;
+    const RulesData *rules_data = data;
+    NMHashState      h;
 
-	_rules_data_assert (rules_data, FALSE);
+    _rules_data_assert(rules_data, FALSE);
 
-	nm_hash_init (&h, 269297543u);
-	nm_platform_routing_rule_hash_update (NMP_OBJECT_CAST_ROUTING_RULE (rules_data->obj),
-	                                      NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID,
-	                                      &h);
-	nm_hash_update_val (&h, rules_data->user_tag);
-	return nm_hash_complete (&h);
+    nm_hash_init(&h, 269297543u);
+    nm_platform_routing_rule_hash_update(NMP_OBJECT_CAST_ROUTING_RULE(rules_data->obj),
+                                         NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID,
+                                         &h);
+    nm_hash_update_val(&h, rules_data->user_tag);
+    return nm_hash_complete(&h);
 }
 
 static gboolean
-_rules_data_equal (gconstpointer data_a, gconstpointer data_b)
+_rules_data_equal(gconstpointer data_a, gconstpointer data_b)
 {
-	const RulesData *rules_data_a = data_a;
-	const RulesData *rules_data_b = data_b;
+    const RulesData *rules_data_a = data_a;
+    const RulesData *rules_data_b = data_b;
 
-	_rules_data_assert (rules_data_a, FALSE);
-	_rules_data_assert (rules_data_b, FALSE);
+    _rules_data_assert(rules_data_a, FALSE);
+    _rules_data_assert(rules_data_b, FALSE);
 
-	return    rules_data_a->user_tag == rules_data_b->user_tag
-	       && (nm_platform_routing_rule_cmp (NMP_OBJECT_CAST_ROUTING_RULE (rules_data_a->obj),
-	                                         NMP_OBJECT_CAST_ROUTING_RULE (rules_data_b->obj),
-	                                         NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID) == 0);
+    return rules_data_a->user_tag == rules_data_b->user_tag
+           && (nm_platform_routing_rule_cmp(NMP_OBJECT_CAST_ROUTING_RULE(rules_data_a->obj),
+                                            NMP_OBJECT_CAST_ROUTING_RULE(rules_data_b->obj),
+                                            NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID)
+               == 0);
 }
 
 static void
-_rules_data_destroy (gpointer data)
+_rules_data_destroy(gpointer data)
 {
-	RulesData *rules_data = data;
+    RulesData *rules_data = data;
 
-	_rules_data_assert (rules_data, FALSE);
+    _rules_data_assert(rules_data, FALSE);
 
-	c_list_unlink_stale (&rules_data->obj_lst);
-	c_list_unlink_stale (&rules_data->user_tag_lst);
-	nmp_object_unref (rules_data->obj);
-	g_slice_free (RulesData, rules_data);
+    c_list_unlink_stale(&rules_data->obj_lst);
+    c_list_unlink_stale(&rules_data->user_tag_lst);
+    nmp_object_unref(rules_data->obj);
+    g_slice_free(RulesData, rules_data);
 }
 
 static const RulesData *
-_rules_obj_get_best_data (RulesObjData *obj_data)
+_rules_obj_get_best_data(RulesObjData *obj_data)
 {
-	RulesData *rules_data;
-	const RulesData *rd_best = NULL;
-
-	c_list_for_each_entry (rules_data, &obj_data->obj_lst_head, obj_lst) {
-
-		_rules_data_assert (rules_data, TRUE);
-
-		if (rd_best) {
-			if (rd_best->track_priority_val > rules_data->track_priority_val)
-				continue;
-			if (rd_best->track_priority_val == rules_data->track_priority_val) {
-				if (   rd_best->track_priority_present
-				    || !rules_data->track_priority_present) {
-					/* if the priorities are identical, then "present" wins over
-					 * "!present" (absent). */
-					continue;
-				}
-			}
-		}
-
-		rd_best = rules_data;
-	}
-
-	return rd_best;
+    RulesData *      rules_data;
+    const RulesData *rd_best = NULL;
+
+    c_list_for_each_entry (rules_data, &obj_data->obj_lst_head, obj_lst) {
+        _rules_data_assert(rules_data, TRUE);
+
+        if (rd_best) {
+            if (rd_best->track_priority_val > rules_data->track_priority_val)
+                continue;
+            if (rd_best->track_priority_val == rules_data->track_priority_val) {
+                if (rd_best->track_priority_present || !rules_data->track_priority_present) {
+                    /* if the priorities are identical, then "present" wins over
+                     * "!present" (absent). */
+                    continue;
+                }
+            }
+        }
+
+        rd_best = rules_data;
+    }
+
+    return rd_best;
 }
 
 static guint
-_rules_obj_hash (gconstpointer data)
+_rules_obj_hash(gconstpointer data)
 {
-	const RulesObjData *obj_data = data;
-	NMHashState h;
-
-	nm_hash_init (&h, 432817559u);
-	nm_platform_routing_rule_hash_update (NMP_OBJECT_CAST_ROUTING_RULE (obj_data->obj),
-	                                      NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID,
-	                                      &h);
-	return nm_hash_complete (&h);
+    const RulesObjData *obj_data = data;
+    NMHashState         h;
+
+    nm_hash_init(&h, 432817559u);
+    nm_platform_routing_rule_hash_update(NMP_OBJECT_CAST_ROUTING_RULE(obj_data->obj),
+                                         NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID,
+                                         &h);
+    return nm_hash_complete(&h);
 }
 
 static gboolean
-_rules_obj_equal (gconstpointer data_a, gconstpointer data_b)
+_rules_obj_equal(gconstpointer data_a, gconstpointer data_b)
 {
-	const RulesObjData *obj_data_a = data_a;
-	const RulesObjData *obj_data_b = data_b;
+    const RulesObjData *obj_data_a = data_a;
+    const RulesObjData *obj_data_b = data_b;
 
-	return (nm_platform_routing_rule_cmp (NMP_OBJECT_CAST_ROUTING_RULE (obj_data_a->obj),
-	                                      NMP_OBJECT_CAST_ROUTING_RULE (obj_data_b->obj),
-	                                      NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID) == 0);
+    return (nm_platform_routing_rule_cmp(NMP_OBJECT_CAST_ROUTING_RULE(obj_data_a->obj),
+                                         NMP_OBJECT_CAST_ROUTING_RULE(obj_data_b->obj),
+                                         NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID)
+            == 0);
 }
 
 static void
-_rules_obj_destroy (gpointer data)
+_rules_obj_destroy(gpointer data)
 {
-	RulesObjData *obj_data = data;
+    RulesObjData *obj_data = data;
 
-	c_list_unlink_stale (&obj_data->obj_lst_head);
-	nmp_object_unref (obj_data->obj);
-	g_slice_free (RulesObjData, obj_data);
+    c_list_unlink_stale(&obj_data->obj_lst_head);
+    nmp_object_unref(obj_data->obj);
+    g_slice_free(RulesObjData, obj_data);
 }
 
 static guint
-_rules_user_tag_hash (gconstpointer data)
+_rules_user_tag_hash(gconstpointer data)
 {
-	const RulesUserTagData *user_tag_data = data;
+    const RulesUserTagData *user_tag_data = data;
 
-	return nm_hash_val (644693447u, user_tag_data->user_tag);
+    return nm_hash_val(644693447u, user_tag_data->user_tag);
 }
 
 static gboolean
-_rules_user_tag_equal (gconstpointer data_a, gconstpointer data_b)
+_rules_user_tag_equal(gconstpointer data_a, gconstpointer data_b)
 {
-	const RulesUserTagData *user_tag_data_a = data_a;
-	const RulesUserTagData *user_tag_data_b = data_b;
+    const RulesUserTagData *user_tag_data_a = data_a;
+    const RulesUserTagData *user_tag_data_b = data_b;
 
-	return user_tag_data_a->user_tag == user_tag_data_b->user_tag;
+    return user_tag_data_a->user_tag == user_tag_data_b->user_tag;
 }
 
 static void
-_rules_user_tag_destroy (gpointer data)
+_rules_user_tag_destroy(gpointer data)
 {
-	RulesUserTagData *user_tag_data = data;
+    RulesUserTagData *user_tag_data = data;
 
-	c_list_unlink_stale (&user_tag_data->user_tag_lst_head);
-	g_slice_free (RulesUserTagData, user_tag_data);
+    c_list_unlink_stale(&user_tag_data->user_tag_lst_head);
+    g_slice_free(RulesUserTagData, user_tag_data);
 }
 
 static RulesData *
-_rules_data_lookup (GHashTable *by_data,
-                    const NMPObject *obj,
-                    gconstpointer user_tag)
+_rules_data_lookup(GHashTable *by_data, const NMPObject *obj, gconstpointer user_tag)
 {
-	RulesData rules_data_needle = {
-		.obj      = obj,
-		.user_tag = user_tag,
-	};
+    RulesData rules_data_needle = {
+        .obj      = obj,
+        .user_tag = user_tag,
+    };
 
-	return g_hash_table_lookup (by_data, &rules_data_needle);
+    return g_hash_table_lookup(by_data, &rules_data_needle);
 }
 
 /**
@@ -305,496 +307,502 @@ _rules_data_lookup (GHashTable *by_data,
  *   The purpose here is to set this to %NMP_RULES_MANAGER_EXTERN_WEAKLY_TRACKED_USER_TAG.
  */
 void
-nmp_rules_manager_track (NMPRulesManager *self,
-                         const NMPlatformRoutingRule *routing_rule,
-                         gint32 track_priority,
-                         gconstpointer user_tag,
-                         gconstpointer user_tag_untrack)
+nmp_rules_manager_track(NMPRulesManager *            self,
+                        const NMPlatformRoutingRule *routing_rule,
+                        gint32                       track_priority,
+                        gconstpointer                user_tag,
+                        gconstpointer                user_tag_untrack)
 {
-	NMPObject obj_stack;
-	const NMPObject *p_obj_stack;
-	RulesData *rules_data;
-	RulesObjData *obj_data;
-	RulesUserTagData *user_tag_data;
-	gboolean changed = FALSE;
-	guint32 track_priority_val;
-	gboolean track_priority_present;
-
-	g_return_if_fail (NMP_IS_RULES_MANAGER (self));
-	g_return_if_fail (routing_rule);
-	g_return_if_fail (user_tag);
-	nm_assert (track_priority != G_MININT32);
-
-	_rules_init (self);
-
-	p_obj_stack = nmp_object_stackinit (&obj_stack, NMP_OBJECT_TYPE_ROUTING_RULE, routing_rule);
-
-	nm_assert (nmp_object_is_visible (p_obj_stack));
-
-	if (track_priority >= 0) {
-		track_priority_val = track_priority;
-		track_priority_present = TRUE;
-	} else {
-		track_priority_val = -track_priority;
-		track_priority_present = FALSE;
-	}
-
-	rules_data = _rules_data_lookup (self->by_data, p_obj_stack, user_tag);
-
-	if (!rules_data) {
-		rules_data = g_slice_new (RulesData);
-		*rules_data = (RulesData) {
-			.obj                    = nm_dedup_multi_index_obj_intern (nm_platform_get_multi_idx (self->platform),
-			                                                           p_obj_stack),
-			.user_tag               = user_tag,
-			.track_priority_val     = track_priority_val,
-			.track_priority_present = track_priority_present,
-			.dirty                  = FALSE,
-		};
-		g_hash_table_add (self->by_data, rules_data);
-
-		obj_data = g_hash_table_lookup (self->by_obj, &rules_data->obj);
-		if (!obj_data) {
-			obj_data = g_slice_new (RulesObjData);
-			*obj_data = (RulesObjData) {
-				.obj          = nmp_object_ref (rules_data->obj),
-				.obj_lst_head = C_LIST_INIT (obj_data->obj_lst_head),
-				.config_state = CONFIG_STATE_NONE,
-			};
-			g_hash_table_add (self->by_obj, obj_data);
-		}
-		c_list_link_tail (&obj_data->obj_lst_head, &rules_data->obj_lst);
-
-		user_tag_data = g_hash_table_lookup (self->by_user_tag, &rules_data->user_tag);
-		if (!user_tag_data) {
-			user_tag_data = g_slice_new (RulesUserTagData);
-			*user_tag_data = (RulesUserTagData) {
-				.user_tag          = user_tag,
-				.user_tag_lst_head = C_LIST_INIT (user_tag_data->user_tag_lst_head),
-			};
-			g_hash_table_add (self->by_user_tag, user_tag_data);
-		}
-		c_list_link_tail (&user_tag_data->user_tag_lst_head, &rules_data->user_tag_lst);
-		changed = TRUE;
-	} else {
-		rules_data->dirty = FALSE;
-		if (   rules_data->track_priority_val != track_priority_val
-		    || rules_data->track_priority_present != track_priority_present) {
-			rules_data->track_priority_val = track_priority_val;
-			rules_data->track_priority_present = track_priority_present;
-			changed = TRUE;
-		}
-	}
-
-	if (user_tag_untrack) {
-		if (user_tag != user_tag_untrack) {
-			RulesData *rules_data_untrack;
-
-			rules_data_untrack = _rules_data_lookup (self->by_data, p_obj_stack, user_tag_untrack);
-			if (rules_data_untrack)
-				_rules_data_untrack (self, rules_data_untrack, FALSE, TRUE);
-		} else
-			nm_assert_not_reached ();
-	}
-
-	_rules_data_assert (rules_data, TRUE);
-
-	if (changed) {
-		_LOGD ("routing-rule: track ["NM_HASH_OBFUSCATE_PTR_FMT",%s%u] \"%s\")",
-		       _USER_TAG_LOG (rules_data->user_tag),
-		       ( rules_data->track_priority_val == 0
-		        ? ""
-		        : (  rules_data->track_priority_present
-		           ? "+"
-		           : "-")),
-		       (guint) rules_data->track_priority_val,
-		       nmp_object_to_string (rules_data->obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
-	}
+    NMPObject         obj_stack;
+    const NMPObject * p_obj_stack;
+    RulesData *       rules_data;
+    RulesObjData *    obj_data;
+    RulesUserTagData *user_tag_data;
+    gboolean          changed = FALSE;
+    guint32           track_priority_val;
+    gboolean          track_priority_present;
+
+    g_return_if_fail(NMP_IS_RULES_MANAGER(self));
+    g_return_if_fail(routing_rule);
+    g_return_if_fail(user_tag);
+    nm_assert(track_priority != G_MININT32);
+
+    _rules_init(self);
+
+    p_obj_stack = nmp_object_stackinit(&obj_stack, NMP_OBJECT_TYPE_ROUTING_RULE, routing_rule);
+
+    nm_assert(nmp_object_is_visible(p_obj_stack));
+
+    if (track_priority >= 0) {
+        track_priority_val     = track_priority;
+        track_priority_present = TRUE;
+    } else {
+        track_priority_val     = -track_priority;
+        track_priority_present = FALSE;
+    }
+
+    rules_data = _rules_data_lookup(self->by_data, p_obj_stack, user_tag);
+
+    if (!rules_data) {
+        rules_data  = g_slice_new(RulesData);
+        *rules_data = (RulesData){
+            .obj      = nm_dedup_multi_index_obj_intern(nm_platform_get_multi_idx(self->platform),
+                                                   p_obj_stack),
+            .user_tag = user_tag,
+            .track_priority_val     = track_priority_val,
+            .track_priority_present = track_priority_present,
+            .dirty                  = FALSE,
+        };
+        g_hash_table_add(self->by_data, rules_data);
+
+        obj_data = g_hash_table_lookup(self->by_obj, &rules_data->obj);
+        if (!obj_data) {
+            obj_data  = g_slice_new(RulesObjData);
+            *obj_data = (RulesObjData){
+                .obj          = nmp_object_ref(rules_data->obj),
+                .obj_lst_head = C_LIST_INIT(obj_data->obj_lst_head),
+                .config_state = CONFIG_STATE_NONE,
+            };
+            g_hash_table_add(self->by_obj, obj_data);
+        }
+        c_list_link_tail(&obj_data->obj_lst_head, &rules_data->obj_lst);
+
+        user_tag_data = g_hash_table_lookup(self->by_user_tag, &rules_data->user_tag);
+        if (!user_tag_data) {
+            user_tag_data  = g_slice_new(RulesUserTagData);
+            *user_tag_data = (RulesUserTagData){
+                .user_tag          = user_tag,
+                .user_tag_lst_head = C_LIST_INIT(user_tag_data->user_tag_lst_head),
+            };
+            g_hash_table_add(self->by_user_tag, user_tag_data);
+        }
+        c_list_link_tail(&user_tag_data->user_tag_lst_head, &rules_data->user_tag_lst);
+        changed = TRUE;
+    } else {
+        rules_data->dirty = FALSE;
+        if (rules_data->track_priority_val != track_priority_val
+            || rules_data->track_priority_present != track_priority_present) {
+            rules_data->track_priority_val     = track_priority_val;
+            rules_data->track_priority_present = track_priority_present;
+            changed                            = TRUE;
+        }
+    }
+
+    if (user_tag_untrack) {
+        if (user_tag != user_tag_untrack) {
+            RulesData *rules_data_untrack;
+
+            rules_data_untrack = _rules_data_lookup(self->by_data, p_obj_stack, user_tag_untrack);
+            if (rules_data_untrack)
+                _rules_data_untrack(self, rules_data_untrack, FALSE, TRUE);
+        } else
+            nm_assert_not_reached();
+    }
+
+    _rules_data_assert(rules_data, TRUE);
+
+    if (changed) {
+        _LOGD("routing-rule: track [" NM_HASH_OBFUSCATE_PTR_FMT ",%s%u] \"%s\")",
+              _USER_TAG_LOG(rules_data->user_tag),
+              (rules_data->track_priority_val == 0
+                   ? ""
+                   : (rules_data->track_priority_present ? "+" : "-")),
+              (guint) rules_data->track_priority_val,
+              nmp_object_to_string(rules_data->obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
+    }
 }
 
 static void
-_rules_data_untrack (NMPRulesManager *self,
-                     RulesData *rules_data,
-                     gboolean remove_user_tag_data,
-                     gboolean make_owned_by_us)
+_rules_data_untrack(NMPRulesManager *self,
+                    RulesData *      rules_data,
+                    gboolean         remove_user_tag_data,
+                    gboolean         make_owned_by_us)
 {
-	RulesObjData *obj_data;
+    RulesObjData *obj_data;
 
-	nm_assert (NMP_IS_RULES_MANAGER (self));
-	_rules_data_assert (rules_data, TRUE);
-	nm_assert (self->by_data);
-	nm_assert (g_hash_table_lookup (self->by_data, rules_data) == rules_data);
+    nm_assert(NMP_IS_RULES_MANAGER(self));
+    _rules_data_assert(rules_data, TRUE);
+    nm_assert(self->by_data);
+    nm_assert(g_hash_table_lookup(self->by_data, rules_data) == rules_data);
 
-	_LOGD ("routing-rule: untrack ["NM_HASH_OBFUSCATE_PTR_FMT"] \"%s\"",
-	       _USER_TAG_LOG (rules_data->user_tag),
-	       nmp_object_to_string (rules_data->obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
+    _LOGD("routing-rule: untrack [" NM_HASH_OBFUSCATE_PTR_FMT "] \"%s\"",
+          _USER_TAG_LOG(rules_data->user_tag),
+          nmp_object_to_string(rules_data->obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
 
 #if NM_MORE_ASSERTS
-	{
-		RulesUserTagData *user_tag_data;
+    {
+        RulesUserTagData *user_tag_data;
 
-		user_tag_data = g_hash_table_lookup (self->by_user_tag, &rules_data->user_tag);
-		nm_assert (user_tag_data);
-		nm_assert (c_list_contains (&user_tag_data->user_tag_lst_head, &rules_data->user_tag_lst));
-	}
+        user_tag_data = g_hash_table_lookup(self->by_user_tag, &rules_data->user_tag);
+        nm_assert(user_tag_data);
+        nm_assert(c_list_contains(&user_tag_data->user_tag_lst_head, &rules_data->user_tag_lst));
+    }
 #endif
 
-	nm_assert (!c_list_is_empty (&rules_data->user_tag_lst));
-
-	obj_data = g_hash_table_lookup (self->by_obj, &rules_data->obj);
-	nm_assert (obj_data);
-	nm_assert (c_list_contains (&obj_data->obj_lst_head, &rules_data->obj_lst));
-	nm_assert (obj_data == g_hash_table_lookup (self->by_obj, &rules_data->obj));
-
-	if (make_owned_by_us) {
-		if (obj_data->config_state == CONFIG_STATE_NONE) {
-			/* we need to mark this entry that it requires a touch on the next
-			 * sync. */
-			obj_data->config_state = CONFIG_STATE_OWNED_BY_US;
-		}
-	} else if (   remove_user_tag_data
-	           && c_list_length_is (&rules_data->user_tag_lst, 1))
-		g_hash_table_remove (self->by_user_tag, &rules_data->user_tag);
-
-	/* if obj_data is marked to be "added_by_us" or "removed_by_us", we need to keep this entry
-	 * around for the next sync -- so that we can undo what we did earlier. */
-	if (   obj_data->config_state == CONFIG_STATE_NONE
-	    && c_list_length_is (&rules_data->obj_lst, 1))
-		g_hash_table_remove (self->by_obj, &rules_data->obj);
-
-	g_hash_table_remove (self->by_data, rules_data);
+    nm_assert(!c_list_is_empty(&rules_data->user_tag_lst));
+
+    obj_data = g_hash_table_lookup(self->by_obj, &rules_data->obj);
+    nm_assert(obj_data);
+    nm_assert(c_list_contains(&obj_data->obj_lst_head, &rules_data->obj_lst));
+    nm_assert(obj_data == g_hash_table_lookup(self->by_obj, &rules_data->obj));
+
+    if (make_owned_by_us) {
+        if (obj_data->config_state == CONFIG_STATE_NONE) {
+            /* we need to mark this entry that it requires a touch on the next
+             * sync. */
+            obj_data->config_state = CONFIG_STATE_OWNED_BY_US;
+        }
+    } else if (remove_user_tag_data && c_list_length_is(&rules_data->user_tag_lst, 1))
+        g_hash_table_remove(self->by_user_tag, &rules_data->user_tag);
+
+    /* if obj_data is marked to be "added_by_us" or "removed_by_us", we need to keep this entry
+     * around for the next sync -- so that we can undo what we did earlier. */
+    if (obj_data->config_state == CONFIG_STATE_NONE && c_list_length_is(&rules_data->obj_lst, 1))
+        g_hash_table_remove(self->by_obj, &rules_data->obj);
+
+    g_hash_table_remove(self->by_data, rules_data);
 }
 
 void
-nmp_rules_manager_untrack (NMPRulesManager *self,
-                           const NMPlatformRoutingRule *routing_rule,
-                           gconstpointer user_tag)
+nmp_rules_manager_untrack(NMPRulesManager *            self,
+                          const NMPlatformRoutingRule *routing_rule,
+                          gconstpointer                user_tag)
 {
-	NMPObject obj_stack;
-	const NMPObject *p_obj_stack;
-	RulesData *rules_data;
+    NMPObject        obj_stack;
+    const NMPObject *p_obj_stack;
+    RulesData *      rules_data;
 
-	g_return_if_fail (NMP_IS_RULES_MANAGER (self));
-	g_return_if_fail (routing_rule);
-	g_return_if_fail (user_tag);
+    g_return_if_fail(NMP_IS_RULES_MANAGER(self));
+    g_return_if_fail(routing_rule);
+    g_return_if_fail(user_tag);
 
-	_rules_init (self);
+    _rules_init(self);
 
-	p_obj_stack = nmp_object_stackinit (&obj_stack, NMP_OBJECT_TYPE_ROUTING_RULE, routing_rule);
+    p_obj_stack = nmp_object_stackinit(&obj_stack, NMP_OBJECT_TYPE_ROUTING_RULE, routing_rule);
 
-	nm_assert (nmp_object_is_visible (p_obj_stack));
+    nm_assert(nmp_object_is_visible(p_obj_stack));
 
-	rules_data = _rules_data_lookup (self->by_data, p_obj_stack, user_tag);
-	if (rules_data)
-		_rules_data_untrack (self, rules_data, TRUE, FALSE);
+    rules_data = _rules_data_lookup(self->by_data, p_obj_stack, user_tag);
+    if (rules_data)
+        _rules_data_untrack(self, rules_data, TRUE, FALSE);
 }
 
 void
-nmp_rules_manager_set_dirty (NMPRulesManager *self,
-                             gconstpointer user_tag)
+nmp_rules_manager_set_dirty(NMPRulesManager *self, gconstpointer user_tag)
 {
-	RulesData *rules_data;
-	RulesUserTagData *user_tag_data;
+    RulesData *       rules_data;
+    RulesUserTagData *user_tag_data;
 
-	g_return_if_fail (NMP_IS_RULES_MANAGER (self));
-	g_return_if_fail (user_tag);
+    g_return_if_fail(NMP_IS_RULES_MANAGER(self));
+    g_return_if_fail(user_tag);
 
-	if (!self->by_data)
-		return;
+    if (!self->by_data)
+        return;
 
-	user_tag_data = g_hash_table_lookup (self->by_user_tag, &user_tag);
-	if (!user_tag_data)
-		return;
+    user_tag_data = g_hash_table_lookup(self->by_user_tag, &user_tag);
+    if (!user_tag_data)
+        return;
 
-	c_list_for_each_entry (rules_data, &user_tag_data->user_tag_lst_head, user_tag_lst)
-		rules_data->dirty = TRUE;
+    c_list_for_each_entry (rules_data, &user_tag_data->user_tag_lst_head, user_tag_lst)
+        rules_data->dirty = TRUE;
 }
 
 void
-nmp_rules_manager_untrack_all (NMPRulesManager *self,
-                               gconstpointer user_tag,
-                               gboolean all /* or only dirty */)
+nmp_rules_manager_untrack_all(NMPRulesManager *self,
+                              gconstpointer    user_tag,
+                              gboolean         all /* or only dirty */)
 {
-	RulesData *rules_data;
-	RulesData *rules_data_safe;
-	RulesUserTagData *user_tag_data;
-
-	g_return_if_fail (NMP_IS_RULES_MANAGER (self));
-	g_return_if_fail (user_tag);
-
-	if (!self->by_data)
-		return;
-
-	user_tag_data = g_hash_table_lookup (self->by_user_tag, &user_tag);
-	if (!user_tag_data)
-		return;
-
-	c_list_for_each_entry_safe (rules_data, rules_data_safe, &user_tag_data->user_tag_lst_head, user_tag_lst) {
-		if (   all
-		    || rules_data->dirty)
-			_rules_data_untrack (self, rules_data, FALSE, FALSE);
-	}
-	if (c_list_is_empty (&user_tag_data->user_tag_lst_head))
-		g_hash_table_remove (self->by_user_tag, user_tag_data);
+    RulesData *       rules_data;
+    RulesData *       rules_data_safe;
+    RulesUserTagData *user_tag_data;
+
+    g_return_if_fail(NMP_IS_RULES_MANAGER(self));
+    g_return_if_fail(user_tag);
+
+    if (!self->by_data)
+        return;
+
+    user_tag_data = g_hash_table_lookup(self->by_user_tag, &user_tag);
+    if (!user_tag_data)
+        return;
+
+    c_list_for_each_entry_safe (rules_data,
+                                rules_data_safe,
+                                &user_tag_data->user_tag_lst_head,
+                                user_tag_lst) {
+        if (all || rules_data->dirty)
+            _rules_data_untrack(self, rules_data, FALSE, FALSE);
+    }
+    if (c_list_is_empty(&user_tag_data->user_tag_lst_head))
+        g_hash_table_remove(self->by_user_tag, user_tag_data);
 }
 
 void
-nmp_rules_manager_sync (NMPRulesManager *self,
-                        gboolean keep_deleted_rules)
+nmp_rules_manager_sync(NMPRulesManager *self, gboolean keep_deleted_rules)
 {
-	const NMDedupMultiHeadEntry *pl_head_entry;
-	NMDedupMultiIter pl_iter;
-	const NMPObject *plobj;
-	gs_unref_ptrarray GPtrArray *rules_to_delete = NULL;
-	RulesObjData *obj_data;
-	GHashTableIter h_iter;
-	guint i;
-	const RulesData *rd_best;
-
-	g_return_if_fail (NMP_IS_RULES_MANAGER (self));
-
-	if (!self->by_data)
-		return;
-
-	_LOGD ("sync%s", keep_deleted_rules ? " (don't remove any rules)" : "");
-
-	pl_head_entry = nm_platform_lookup_obj_type (self->platform, NMP_OBJECT_TYPE_ROUTING_RULE);
-	if (pl_head_entry) {
-		nmp_cache_iter_for_each (&pl_iter, pl_head_entry, &plobj) {
-			obj_data = g_hash_table_lookup (self->by_obj, &plobj);
-
-			if (!obj_data) {
-				/* this rule is not tracked. It was externally added, hence we
-				 * ignore it. */
-				continue;
-			}
-
-			rd_best = _rules_obj_get_best_data (obj_data);
-			if (rd_best) {
-				if (rd_best->track_priority_present) {
-					if (obj_data->config_state == CONFIG_STATE_OWNED_BY_US)
-						obj_data->config_state = CONFIG_STATE_ADDED_BY_US;
-					continue;
-				}
-				if (rd_best->track_priority_val == 0) {
-					if (!NM_IN_SET (obj_data->config_state, CONFIG_STATE_ADDED_BY_US,
-					                                        CONFIG_STATE_OWNED_BY_US)) {
-						obj_data->config_state = CONFIG_STATE_NONE;
-						continue;
-					}
-					obj_data->config_state = CONFIG_STATE_NONE;
-				}
-			}
-
-			if (keep_deleted_rules) {
-				_LOGD ("forget/leak rule added by us: %s", nmp_object_to_string (plobj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
-				continue;
-			}
-
-			if (!rules_to_delete)
-				rules_to_delete = g_ptr_array_new_with_free_func ((GDestroyNotify) nmp_object_unref);
-
-			g_ptr_array_add (rules_to_delete, (gpointer) nmp_object_ref (plobj));
-
-			obj_data->config_state = CONFIG_STATE_REMOVED_BY_US;
-		}
-	}
-
-	if (rules_to_delete) {
-		for (i = 0; i < rules_to_delete->len; i++)
-			nm_platform_object_delete (self->platform, rules_to_delete->pdata[i]);
-	}
-
-	g_hash_table_iter_init (&h_iter, self->by_obj);
-	while (g_hash_table_iter_next (&h_iter, (gpointer *) &obj_data, NULL)) {
-
-		rd_best = _rules_obj_get_best_data (obj_data);
-
-		if (!rd_best) {
-			g_hash_table_iter_remove (&h_iter);
-			continue;
-		}
-
-		if (!rd_best->track_priority_present) {
-			if (obj_data->config_state == CONFIG_STATE_OWNED_BY_US)
-				obj_data->config_state = CONFIG_STATE_REMOVED_BY_US;
-			continue;
-		}
-		if (rd_best->track_priority_val == 0) {
-			if (!NM_IN_SET (obj_data->config_state, CONFIG_STATE_REMOVED_BY_US,
-			                                        CONFIG_STATE_OWNED_BY_US)) {
-				obj_data->config_state = CONFIG_STATE_NONE;
-				continue;
-			}
-			obj_data->config_state = CONFIG_STATE_NONE;
-		}
-
-		plobj = nm_platform_lookup_obj (self->platform, NMP_CACHE_ID_TYPE_OBJECT_TYPE, obj_data->obj);
-		if (plobj)
-			continue;
-
-		obj_data->config_state = CONFIG_STATE_ADDED_BY_US;
-		nm_platform_routing_rule_add (self->platform, NMP_NLM_FLAG_ADD, NMP_OBJECT_CAST_ROUTING_RULE (obj_data->obj));
-	}
+    const NMDedupMultiHeadEntry *pl_head_entry;
+    NMDedupMultiIter             pl_iter;
+    const NMPObject *            plobj;
+    gs_unref_ptrarray GPtrArray *rules_to_delete = NULL;
+    RulesObjData *               obj_data;
+    GHashTableIter               h_iter;
+    guint                        i;
+    const RulesData *            rd_best;
+
+    g_return_if_fail(NMP_IS_RULES_MANAGER(self));
+
+    if (!self->by_data)
+        return;
+
+    _LOGD("sync%s", keep_deleted_rules ? " (don't remove any rules)" : "");
+
+    pl_head_entry = nm_platform_lookup_obj_type(self->platform, NMP_OBJECT_TYPE_ROUTING_RULE);
+    if (pl_head_entry) {
+        nmp_cache_iter_for_each (&pl_iter, pl_head_entry, &plobj) {
+            obj_data = g_hash_table_lookup(self->by_obj, &plobj);
+
+            if (!obj_data) {
+                /* this rule is not tracked. It was externally added, hence we
+                 * ignore it. */
+                continue;
+            }
+
+            rd_best = _rules_obj_get_best_data(obj_data);
+            if (rd_best) {
+                if (rd_best->track_priority_present) {
+                    if (obj_data->config_state == CONFIG_STATE_OWNED_BY_US)
+                        obj_data->config_state = CONFIG_STATE_ADDED_BY_US;
+                    continue;
+                }
+                if (rd_best->track_priority_val == 0) {
+                    if (!NM_IN_SET(obj_data->config_state,
+                                   CONFIG_STATE_ADDED_BY_US,
+                                   CONFIG_STATE_OWNED_BY_US)) {
+                        obj_data->config_state = CONFIG_STATE_NONE;
+                        continue;
+                    }
+                    obj_data->config_state = CONFIG_STATE_NONE;
+                }
+            }
+
+            if (keep_deleted_rules) {
+                _LOGD("forget/leak rule added by us: %s",
+                      nmp_object_to_string(plobj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
+                continue;
+            }
+
+            if (!rules_to_delete)
+                rules_to_delete = g_ptr_array_new_with_free_func((GDestroyNotify) nmp_object_unref);
+
+            g_ptr_array_add(rules_to_delete, (gpointer) nmp_object_ref(plobj));
+
+            obj_data->config_state = CONFIG_STATE_REMOVED_BY_US;
+        }
+    }
+
+    if (rules_to_delete) {
+        for (i = 0; i < rules_to_delete->len; i++)
+            nm_platform_object_delete(self->platform, rules_to_delete->pdata[i]);
+    }
+
+    g_hash_table_iter_init(&h_iter, self->by_obj);
+    while (g_hash_table_iter_next(&h_iter, (gpointer *) &obj_data, NULL)) {
+        rd_best = _rules_obj_get_best_data(obj_data);
+
+        if (!rd_best) {
+            g_hash_table_iter_remove(&h_iter);
+            continue;
+        }
+
+        if (!rd_best->track_priority_present) {
+            if (obj_data->config_state == CONFIG_STATE_OWNED_BY_US)
+                obj_data->config_state = CONFIG_STATE_REMOVED_BY_US;
+            continue;
+        }
+        if (rd_best->track_priority_val == 0) {
+            if (!NM_IN_SET(obj_data->config_state,
+                           CONFIG_STATE_REMOVED_BY_US,
+                           CONFIG_STATE_OWNED_BY_US)) {
+                obj_data->config_state = CONFIG_STATE_NONE;
+                continue;
+            }
+            obj_data->config_state = CONFIG_STATE_NONE;
+        }
+
+        plobj =
+            nm_platform_lookup_obj(self->platform, NMP_CACHE_ID_TYPE_OBJECT_TYPE, obj_data->obj);
+        if (plobj)
+            continue;
+
+        obj_data->config_state = CONFIG_STATE_ADDED_BY_US;
+        nm_platform_routing_rule_add(self->platform,
+                                     NMP_NLM_FLAG_ADD,
+                                     NMP_OBJECT_CAST_ROUTING_RULE(obj_data->obj));
+    }
 }
 
 void
-nmp_rules_manager_track_from_platform (NMPRulesManager *self,
-                                       NMPlatform *platform,
-                                       int addr_family,
-                                       gint32 tracking_priority,
-                                       gconstpointer user_tag)
+nmp_rules_manager_track_from_platform(NMPRulesManager *self,
+                                      NMPlatform *     platform,
+                                      int              addr_family,
+                                      gint32           tracking_priority,
+                                      gconstpointer    user_tag)
 {
-	NMPLookup lookup;
-	const NMDedupMultiHeadEntry *head_entry;
-	NMDedupMultiIter iter;
-	const NMPObject *o;
+    NMPLookup                    lookup;
+    const NMDedupMultiHeadEntry *head_entry;
+    NMDedupMultiIter             iter;
+    const NMPObject *            o;
 
-	g_return_if_fail (NMP_IS_RULES_MANAGER (self));
+    g_return_if_fail(NMP_IS_RULES_MANAGER(self));
 
-	if (!platform)
-		platform = self->platform;
-	else
-		g_return_if_fail (NM_IS_PLATFORM (platform));
+    if (!platform)
+        platform = self->platform;
+    else
+        g_return_if_fail(NM_IS_PLATFORM(platform));
 
-	nm_assert (NM_IN_SET (addr_family, AF_UNSPEC, AF_INET, AF_INET6));
+    nm_assert(NM_IN_SET(addr_family, AF_UNSPEC, AF_INET, AF_INET6));
 
-	nmp_lookup_init_obj_type (&lookup, NMP_OBJECT_TYPE_ROUTING_RULE);
-	head_entry = nm_platform_lookup (platform, &lookup);
-	nmp_cache_iter_for_each (&iter, head_entry, &o) {
-		const NMPlatformRoutingRule *rr = NMP_OBJECT_CAST_ROUTING_RULE (o);
+    nmp_lookup_init_obj_type(&lookup, NMP_OBJECT_TYPE_ROUTING_RULE);
+    head_entry = nm_platform_lookup(platform, &lookup);
+    nmp_cache_iter_for_each (&iter, head_entry, &o) {
+        const NMPlatformRoutingRule *rr = NMP_OBJECT_CAST_ROUTING_RULE(o);
 
-		if (   addr_family != AF_UNSPEC
-		    && rr->addr_family != addr_family)
-			continue;
+        if (addr_family != AF_UNSPEC && rr->addr_family != addr_family)
+            continue;
 
-		nmp_rules_manager_track (self, rr, tracking_priority, user_tag, NULL);
-	}
+        nmp_rules_manager_track(self, rr, tracking_priority, user_tag, NULL);
+    }
 }
 
 /*****************************************************************************/
 
 void
-nmp_rules_manager_track_default (NMPRulesManager *self,
-                                 int addr_family,
-                                 gint32 track_priority,
-                                 gconstpointer user_tag)
+nmp_rules_manager_track_default(NMPRulesManager *self,
+                                int              addr_family,
+                                gint32           track_priority,
+                                gconstpointer    user_tag)
 {
-	g_return_if_fail (NMP_IS_RULES_MANAGER (self));
-
-	nm_assert (NM_IN_SET (addr_family, AF_UNSPEC, AF_INET, AF_INET6));
-
-	/* track the default rules. See also `man ip-rule`. */
-
-	if (NM_IN_SET (addr_family, AF_UNSPEC, AF_INET)) {
-		nmp_rules_manager_track (self,
-		                         &((NMPlatformRoutingRule) {
-		                             .addr_family = AF_INET,
-		                             .priority    = 0,
-		                             .table       = RT_TABLE_LOCAL,
-		                             .action      = FR_ACT_TO_TBL,
-		                             .protocol    = RTPROT_KERNEL,
-		                         }),
-		                         track_priority,
-		                         user_tag,
-		                         NULL);
-		nmp_rules_manager_track (self,
-		                         &((NMPlatformRoutingRule) {
-		                             .addr_family = AF_INET,
-		                             .priority    = 32766,
-		                             .table       = RT_TABLE_MAIN,
-		                             .action      = FR_ACT_TO_TBL,
-		                             .protocol    = RTPROT_KERNEL,
-		                         }),
-		                         track_priority,
-		                         user_tag,
-		                         NULL);
-		nmp_rules_manager_track (self,
-		                         &((NMPlatformRoutingRule) {
-		                             .addr_family = AF_INET,
-		                             .priority    = 32767,
-		                             .table       = RT_TABLE_DEFAULT,
-		                             .action      = FR_ACT_TO_TBL,
-		                             .protocol    = RTPROT_KERNEL,
-		                         }),
-		                         track_priority,
-		                         user_tag,
-		                         NULL);
-	}
-	if (NM_IN_SET (addr_family, AF_UNSPEC, AF_INET6)) {
-		nmp_rules_manager_track (self,
-		                         &((NMPlatformRoutingRule) {
-		                             .addr_family = AF_INET6,
-		                             .priority    = 0,
-		                             .table       = RT_TABLE_LOCAL,
-		                             .action      = FR_ACT_TO_TBL,
-		                             .protocol    = RTPROT_KERNEL,
-		                         }),
-		                         track_priority,
-		                         user_tag,
-		                         NULL);
-		nmp_rules_manager_track (self,
-		                         &((NMPlatformRoutingRule) {
-		                             .addr_family = AF_INET6,
-		                             .priority    = 32766,
-		                             .table       = RT_TABLE_MAIN,
-		                             .action      = FR_ACT_TO_TBL,
-		                             .protocol    = RTPROT_KERNEL,
-		                         }),
-		                         track_priority,
-		                         user_tag,
-		                         NULL);
-	}
+    g_return_if_fail(NMP_IS_RULES_MANAGER(self));
+
+    nm_assert(NM_IN_SET(addr_family, AF_UNSPEC, AF_INET, AF_INET6));
+
+    /* track the default rules. See also `man ip-rule`. */
+
+    if (NM_IN_SET(addr_family, AF_UNSPEC, AF_INET)) {
+        nmp_rules_manager_track(self,
+                                &((NMPlatformRoutingRule){
+                                    .addr_family = AF_INET,
+                                    .priority    = 0,
+                                    .table       = RT_TABLE_LOCAL,
+                                    .action      = FR_ACT_TO_TBL,
+                                    .protocol    = RTPROT_KERNEL,
+                                }),
+                                track_priority,
+                                user_tag,
+                                NULL);
+        nmp_rules_manager_track(self,
+                                &((NMPlatformRoutingRule){
+                                    .addr_family = AF_INET,
+                                    .priority    = 32766,
+                                    .table       = RT_TABLE_MAIN,
+                                    .action      = FR_ACT_TO_TBL,
+                                    .protocol    = RTPROT_KERNEL,
+                                }),
+                                track_priority,
+                                user_tag,
+                                NULL);
+        nmp_rules_manager_track(self,
+                                &((NMPlatformRoutingRule){
+                                    .addr_family = AF_INET,
+                                    .priority    = 32767,
+                                    .table       = RT_TABLE_DEFAULT,
+                                    .action      = FR_ACT_TO_TBL,
+                                    .protocol    = RTPROT_KERNEL,
+                                }),
+                                track_priority,
+                                user_tag,
+                                NULL);
+    }
+    if (NM_IN_SET(addr_family, AF_UNSPEC, AF_INET6)) {
+        nmp_rules_manager_track(self,
+                                &((NMPlatformRoutingRule){
+                                    .addr_family = AF_INET6,
+                                    .priority    = 0,
+                                    .table       = RT_TABLE_LOCAL,
+                                    .action      = FR_ACT_TO_TBL,
+                                    .protocol    = RTPROT_KERNEL,
+                                }),
+                                track_priority,
+                                user_tag,
+                                NULL);
+        nmp_rules_manager_track(self,
+                                &((NMPlatformRoutingRule){
+                                    .addr_family = AF_INET6,
+                                    .priority    = 32766,
+                                    .table       = RT_TABLE_MAIN,
+                                    .action      = FR_ACT_TO_TBL,
+                                    .protocol    = RTPROT_KERNEL,
+                                }),
+                                track_priority,
+                                user_tag,
+                                NULL);
+    }
 }
 
 static void
-_rules_init (NMPRulesManager *self)
+_rules_init(NMPRulesManager *self)
 {
-	if (self->by_data)
-		return;
-
-	self->by_data      = g_hash_table_new_full (_rules_data_hash,      _rules_data_equal,      NULL, _rules_data_destroy);
-	self->by_obj       = g_hash_table_new_full (_rules_obj_hash,       _rules_obj_equal,       NULL, _rules_obj_destroy);
-	self->by_user_tag  = g_hash_table_new_full (_rules_user_tag_hash,  _rules_user_tag_equal,  NULL, _rules_user_tag_destroy);
+    if (self->by_data)
+        return;
+
+    self->by_data =
+        g_hash_table_new_full(_rules_data_hash, _rules_data_equal, NULL, _rules_data_destroy);
+    self->by_obj =
+        g_hash_table_new_full(_rules_obj_hash, _rules_obj_equal, NULL, _rules_obj_destroy);
+    self->by_user_tag = g_hash_table_new_full(_rules_user_tag_hash,
+                                              _rules_user_tag_equal,
+                                              NULL,
+                                              _rules_user_tag_destroy);
 }
 
 /*****************************************************************************/
 
 NMPRulesManager *
-nmp_rules_manager_new (NMPlatform *platform)
+nmp_rules_manager_new(NMPlatform *platform)
 {
-	NMPRulesManager *self;
+    NMPRulesManager *self;
 
-	g_return_val_if_fail (NM_IS_PLATFORM (platform), NULL);
+    g_return_val_if_fail(NM_IS_PLATFORM(platform), NULL);
 
-	self = g_slice_new (NMPRulesManager);
-	*self = (NMPRulesManager) {
-		.ref_count     = 1,
-		.platform      = g_object_ref (platform),
-	};
-	return self;
+    self  = g_slice_new(NMPRulesManager);
+    *self = (NMPRulesManager){
+        .ref_count = 1,
+        .platform  = g_object_ref(platform),
+    };
+    return self;
 }
 
 void
-nmp_rules_manager_ref (NMPRulesManager *self)
+nmp_rules_manager_ref(NMPRulesManager *self)
 {
-	g_return_if_fail (NMP_IS_RULES_MANAGER (self));
+    g_return_if_fail(NMP_IS_RULES_MANAGER(self));
 
-	self->ref_count++;
+    self->ref_count++;
 }
 
-void nmp_rules_manager_unref (NMPRulesManager *self)
+void
+nmp_rules_manager_unref(NMPRulesManager *self)
 {
-	g_return_if_fail (NMP_IS_RULES_MANAGER (self));
-
-	if (--self->ref_count > 0)
-		return;
-
-	if (self->by_data) {
-		g_hash_table_destroy (self->by_user_tag);
-		g_hash_table_destroy (self->by_obj);
-		g_hash_table_destroy (self->by_data);
-	}
-	g_object_unref (self->platform);
-	g_slice_free (NMPRulesManager, self);
+    g_return_if_fail(NMP_IS_RULES_MANAGER(self));
+
+    if (--self->ref_count > 0)
+        return;
+
+    if (self->by_data) {
+        g_hash_table_destroy(self->by_user_tag);
+        g_hash_table_destroy(self->by_obj);
+        g_hash_table_destroy(self->by_data);
+    }
+    g_object_unref(self->platform);
+    g_slice_free(NMPRulesManager, self);
 }