about summary refs log tree commit diff
path: root/shared/nm-utils
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2019-04-21 21:09:51 +0200
committerMichael Biebl <biebl@debian.org>2019-04-21 21:09:51 +0200
commit85563b7fc7ec2cd21e38debb9b28db342e2e8e7c (patch)
treecce7b0b02d28fae2df9fdf2c1804cacd1500f2d7 /shared/nm-utils
parent9a6dcbf895f9da01768e64b73cec88c16157d91e (diff)
New upstream version 1.18.0 upstream/1.18.0
Diffstat (limited to 'shared/nm-utils')
-rw-r--r--shared/nm-utils/c-list-util.c209
-rw-r--r--shared/nm-utils/c-list-util.h43
-rw-r--r--shared/nm-utils/nm-c-list.h117
-rw-r--r--shared/nm-utils/nm-dedup-multi.c1092
-rw-r--r--shared/nm-utils/nm-dedup-multi.h437
-rw-r--r--shared/nm-utils/nm-enum-utils.c372
-rw-r--r--shared/nm-utils/nm-enum-utils.h48
-rw-r--r--shared/nm-utils/nm-errno.c198
-rw-r--r--shared/nm-utils/nm-errno.h185
-rw-r--r--shared/nm-utils/nm-glib.h567
-rw-r--r--shared/nm-utils/nm-hash-utils.c196
-rw-r--r--shared/nm-utils/nm-hash-utils.h290
-rw-r--r--shared/nm-utils/nm-io-utils.c439
-rw-r--r--shared/nm-utils/nm-io-utils.h63
-rw-r--r--shared/nm-utils/nm-jansson.h49
-rw-r--r--shared/nm-utils/nm-logging-fwd.h113
-rw-r--r--shared/nm-utils/nm-macros-internal.h1707
-rw-r--r--shared/nm-utils/nm-obj.h82
-rw-r--r--shared/nm-utils/nm-random-utils.c165
-rw-r--r--shared/nm-utils/nm-random-utils.h27
-rw-r--r--shared/nm-utils/nm-secret-utils.c161
-rw-r--r--shared/nm-utils/nm-secret-utils.h178
-rw-r--r--shared/nm-utils/nm-shared-utils.c2741
-rw-r--r--shared/nm-utils/nm-shared-utils.h1158
-rw-r--r--shared/nm-utils/nm-test-utils.h11
-rw-r--r--shared/nm-utils/nm-time-utils.c273
-rw-r--r--shared/nm-utils/nm-time-utils.h45
-rw-r--r--shared/nm-utils/nm-udev-utils.c291
-rw-r--r--shared/nm-utils/nm-udev-utils.h48
-rw-r--r--shared/nm-utils/nm-vpn-editor-plugin-call.h2
-rw-r--r--shared/nm-utils/tests/test-shared-general.c203
-rw-r--r--shared/nm-utils/unaligned.h99
32 files changed, 207 insertions, 11402 deletions
diff --git a/shared/nm-utils/c-list-util.c b/shared/nm-utils/c-list-util.c
deleted file mode 100644
index 44ca26a5..00000000
--- a/shared/nm-utils/c-list-util.c
+++ /dev/null
@@ -1,209 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-/* NetworkManager -- Network link manager
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA.
- *
- * (C) Copyright 2017 Red Hat, Inc.
- */
-
-#include "c-list-util.h"
-
-/*****************************************************************************/
-
-/**
- * c_list_relink:
- * @lst: the head list entry
- *
- * Takes an invalid list, that has undefined prev pointers.
- * Only the next pointers are valid, and the tail's next
- * pointer points to %NULL instead of the head.
- *
- * c_list_relink() fixes the list by updating all prev pointers
- * and close the circular linking by pointing the tails' next
- * pointer to @lst.
- *
- * The use of this function is to do a bulk update, that lets the
- * list degredate by not updating the prev pointers. At the end,
- * the list can be fixed by c_list_relink().
- */
-void
-c_list_relink (CList *lst)
-{
-	CList *ls, *ls_prev;
-
-	ls_prev = lst;
-	ls = lst->next;
-	do {
-		ls->prev = ls_prev;
-		ls_prev = ls;
-		ls = ls->next;
-	} while (ls);
-	ls_prev->next = lst;
-	lst->prev = ls_prev;
-}
-
-/*****************************************************************************/
-
-static CList *
-_c_list_srt_split (CList *ls)
-{
-	CList *ls2;
-
-	ls2 = ls;
-	ls = ls->next;
-	if (!ls)
-		return NULL;
-	do {
-		ls = ls->next;
-		if (!ls)
-			break;
-		ls = ls->next;
-		ls2 = ls2->next;
-	} while (ls);
-	ls = ls2->next;
-	ls2->next = NULL;
-	return ls;
-}
-
-static CList *
-_c_list_srt_merge (CList *ls1,
-                   CList *ls2,
-                   CListSortCmp cmp,
-                   const void *user_data)
-{
-	CList *ls;
-	CList head;
-
-	ls = &head;
-	for (;;) {
-		/* while invoking the @cmp function, the list
-		 * elements are not properly linked. Don't try to access
-		 * their next/prev pointers. */
-		if (cmp (ls1, ls2, user_data) <= 0) {
-			ls->next = ls1;
-			ls = ls1;
-			ls1 = ls1->next;
-			if (!ls1)
-				break;
-		} else {
-			ls->next = ls2;
-			ls = ls2;
-			ls2 = ls2->next;
-			if (!ls2)
-				break;
-		}
-	}
-	ls->next = ls1 ?: ls2;
-
-	return head.next;
-}
-
-typedef struct {
-	CList *ls1;
-	CList *ls2;
-	char ls1_sorted;
-} SortStack;
-
-static CList *
-_c_list_sort (CList *ls,
-              CListSortCmp cmp,
-              const void *user_data)
-{
-	/* reserve a huge stack-size. We need roughly log2(n) entries, hence this
-	 * is much more we will ever need. We don't guard for stack-overflow either. */
-	SortStack stack_arr[70];
-	SortStack *stack_head = stack_arr;
-
-	stack_arr[0].ls1 = ls;
-
-	/* A simple top-down, non-recursive, stable merge-sort.
-	 *
-	 * Maybe natural merge-sort would be better, to do better for
-	 * partially sorted lists. */
-_split:
-	stack_head[0].ls2 = _c_list_srt_split (stack_head[0].ls1);
-	if (stack_head[0].ls2) {
-		stack_head[0].ls1_sorted = 0;
-		stack_head[1].ls1 = stack_head[0].ls1;
-		stack_head++;
-		goto _split;
-	}
-
-_backtrack:
-	if (stack_head == stack_arr)
-		return stack_arr[0].ls1;
-
-	stack_head--;
-	if (!stack_head[0].ls1_sorted) {
-		stack_head[0].ls1 = stack_head[1].ls1;
-		stack_head[0].ls1_sorted = 1;
-		stack_head[1].ls1 = stack_head[0].ls2;
-		stack_head++;
-		goto _split;
-	}
-
-	stack_head[0].ls1 = _c_list_srt_merge (stack_head[0].ls1, stack_head[1].ls1, cmp, user_data);
-	goto _backtrack;
-}
-
-/**
- * c_list_sort_headless:
- * @lst: the list.
- * @cmp: compare function for sorting. While comparing two
- *   CList elements, their next/prev pointers are in undefined
- *   state.
- * @user_data: user data for @cmp.
- *
- * Sorts the list @lst according to @cmp. Contrary to
- * c_list_sort(), @lst is not the list head but a
- * valid entry as well. This function returns the new
- * list head.
- */
-CList *
-c_list_sort_headless (CList *lst,
-                      CListSortCmp cmp,
-                      const void *user_data)
-{
-	if (!c_list_is_empty (lst)) {
-		lst->prev->next = NULL;
-		lst = _c_list_sort (lst, cmp, user_data);
-		c_list_relink (lst);
-	}
-	return lst;
-}
-
-/**
- * c_list_sort:
- * @head: the list head.
- * @cmp: compare function for sorting. While comparing two
- *   CList elements, their next/prev pointers are in undefined
- *   state.
- * @user_data: user data for @cmp.
- *
- * Sorts the list @head according to @cmp.
- */
-void
-c_list_sort (CList *head,
-             CListSortCmp cmp,
-             const void *user_data)
-{
-	if (   !c_list_is_empty (head)
-	    && head->next->next != head) {
-		head->prev->next = NULL;
-		head->next = _c_list_sort (head->next, cmp, user_data);
-		c_list_relink (head);
-	}
-}
diff --git a/shared/nm-utils/c-list-util.h b/shared/nm-utils/c-list-util.h
deleted file mode 100644
index e87f1c19..00000000
--- a/shared/nm-utils/c-list-util.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-/* NetworkManager -- Network link manager
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA.
- *
- * (C) Copyright 2017 Red Hat, Inc.
- */
-
-#ifndef __C_LIST_UTIL_H__
-#define __C_LIST_UTIL_H__
-
-#include "c-list/src/c-list.h"
-
-/*****************************************************************************/
-
-void c_list_relink (CList *lst);
-
-typedef int (*CListSortCmp) (const CList *a,
-                             const CList *b,
-                             const void *user_data);
-
-CList *c_list_sort_headless (CList *lst,
-                             CListSortCmp cmp,
-                             const void *user_data);
-
-void c_list_sort (CList *head,
-                  CListSortCmp cmp,
-                  const void *user_data);
-
-#endif /* __C_LIST_UTIL_H__ */
diff --git a/shared/nm-utils/nm-c-list.h b/shared/nm-utils/nm-c-list.h
deleted file mode 100644
index 5c73f574..00000000
--- a/shared/nm-utils/nm-c-list.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-/* NetworkManager -- Network link manager
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA.
- *
- * (C) Copyright 2014 Red Hat, Inc.
- */
-
-#ifndef __NM_C_LIST_H__
-#define __NM_C_LIST_H__
-
-#include "c-list/src/c-list.h"
-
-/*****************************************************************************/
-
-#define nm_c_list_contains_entry(list, what, member) \
-	({ \
-		typeof (what) _what = (what); \
-		\
-		_what && c_list_contains (list, &_what->member); \
-	})
-
-typedef struct {
-	CList lst;
-	void *data;
-} NMCListElem;
-
-static inline NMCListElem *
-nm_c_list_elem_new_stale (void *data)
-{
-	NMCListElem *elem;
-
-	elem = g_slice_new (NMCListElem);
-	elem->data = data;
-	return elem;
-}
-
-static inline void *
-nm_c_list_elem_get (CList *lst)
-{
-	if (!lst)
-		return NULL;
-	return c_list_entry (lst, NMCListElem, lst)->data;
-}
-
-static inline void
-nm_c_list_elem_free (NMCListElem *elem)
-{
-	if (elem) {
-		c_list_unlink_stale (&elem->lst);
-		g_slice_free (NMCListElem, elem);
-	}
-}
-
-static inline void
-nm_c_list_elem_free_all (CList *head, GDestroyNotify free_fcn)
-{
-	NMCListElem *elem;
-
-	while ((elem = c_list_first_entry (head, NMCListElem, lst))) {
-		if (free_fcn)
-			free_fcn (elem->data);
-		c_list_unlink_stale (&elem->lst);
-		g_slice_free (NMCListElem, elem);
-	}
-}
-
-/*****************************************************************************/
-
-static inline gboolean
-nm_c_list_move_before (CList *lst, CList *elem)
-{
-	nm_assert (lst);
-	nm_assert (elem);
-	nm_assert (c_list_contains (lst, elem));
-
-	if (   lst != elem
-	    && lst->prev != elem) {
-		c_list_unlink_stale (elem);
-		c_list_link_before (lst, elem);
-		return TRUE;
-	}
-	return FALSE;
-}
-#define nm_c_list_move_tail(lst, elem) nm_c_list_move_before (lst, elem)
-
-static inline gboolean
-nm_c_list_move_after (CList *lst, CList *elem)
-{
-	nm_assert (lst);
-	nm_assert (elem);
-	nm_assert (c_list_contains (lst, elem));
-
-	if (   lst != elem
-	    && lst->next != elem) {
-		c_list_unlink_stale (elem);
-		c_list_link_after (lst, elem);
-		return TRUE;
-	}
-	return FALSE;
-}
-#define nm_c_list_move_front(lst, elem) nm_c_list_move_after (lst, elem)
-
-#endif /* __NM_C_LIST_H__ */
diff --git a/shared/nm-utils/nm-dedup-multi.c b/shared/nm-utils/nm-dedup-multi.c
deleted file mode 100644
index 5bdc3e3c..00000000
--- a/shared/nm-utils/nm-dedup-multi.c
+++ /dev/null
@@ -1,1092 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-/* NetworkManager -- Network link manager
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA.
- *
- * (C) Copyright 2017 Red Hat, Inc.
- */
-
-#include "nm-default.h"
-
-#include "nm-dedup-multi.h"
-
-#include "nm-hash-utils.h"
-#include "nm-c-list.h"
-
-/*****************************************************************************/
-
-typedef struct {
-	/* the stack-allocated lookup entry. It has a compatible
-	 * memory layout with NMDedupMultiEntry and NMDedupMultiHeadEntry.
-	 *
-	 * It is recognizable by having lst_entries_sentinel.next set to NULL.
-	 * Contrary to the other entries, which have lst_entries.next
-	 * always non-NULL.
-	 * */
-	CList lst_entries_sentinel;
-	const NMDedupMultiObj *obj;
-	const NMDedupMultiIdxType *idx_type;
-	bool lookup_head;
-} LookupEntry;
-
-struct _NMDedupMultiIndex {
-	int ref_count;
-	GHashTable *idx_entries;
-	GHashTable *idx_objs;
-};
-
-/*****************************************************************************/
-
-static void
-ASSERT_idx_type (const NMDedupMultiIdxType *idx_type)
-{
-	nm_assert (idx_type);
-#if NM_MORE_ASSERTS > 10
-	nm_assert (idx_type->klass);
-	nm_assert (idx_type->klass->idx_obj_id_hash_update);
-	nm_assert (idx_type->klass->idx_obj_id_equal);
-	nm_assert (!!idx_type->klass->idx_obj_partition_hash_update == !!idx_type->klass->idx_obj_partition_equal);
-	nm_assert (idx_type->lst_idx_head.next);
-#endif
-}
-
-void
-nm_dedup_multi_idx_type_init (NMDedupMultiIdxType *idx_type,
-                              const NMDedupMultiIdxTypeClass *klass)
-{
-	nm_assert (idx_type);
-	nm_assert (klass);
-
-	memset (idx_type, 0, sizeof (*idx_type));
-	idx_type->klass = klass;
-	c_list_init (&idx_type->lst_idx_head);
-
-	ASSERT_idx_type (idx_type);
-}
-
-/*****************************************************************************/
-
-static NMDedupMultiEntry *
-_entry_lookup_obj (const NMDedupMultiIndex *self,
-                   const NMDedupMultiIdxType *idx_type,
-                   const NMDedupMultiObj *obj)
-{
-	const LookupEntry stack_entry = {
-		.obj = obj,
-		.idx_type = idx_type,
-		.lookup_head = FALSE,
-	};
-
-	ASSERT_idx_type (idx_type);
-	return g_hash_table_lookup (self->idx_entries, &stack_entry);
-}
-
-static NMDedupMultiHeadEntry *
-_entry_lookup_head (const NMDedupMultiIndex *self,
-                    const NMDedupMultiIdxType *idx_type,
-                    const NMDedupMultiObj *obj)
-{
-	NMDedupMultiHeadEntry *head_entry;
-	const LookupEntry stack_entry = {
-		.obj = obj,
-		.idx_type = idx_type,
-		.lookup_head = TRUE,
-	};
-
-	ASSERT_idx_type (idx_type);
-
-	if (!idx_type->klass->idx_obj_partition_equal) {
-		if (c_list_is_empty (&idx_type->lst_idx_head))
-			head_entry = NULL;
-		else {
-			nm_assert (c_list_length (&idx_type->lst_idx_head) == 1);
-			head_entry = c_list_entry (idx_type->lst_idx_head.next, NMDedupMultiHeadEntry, lst_idx);
-		}
-		nm_assert (head_entry == g_hash_table_lookup (self->idx_entries, &stack_entry));
-		return head_entry;
-	}
-
-	return g_hash_table_lookup (self->idx_entries, &stack_entry);
-}
-
-static void
-_entry_unpack (const NMDedupMultiEntry *entry,
-               const NMDedupMultiIdxType **out_idx_type,
-               const NMDedupMultiObj **out_obj,
-               gboolean *out_lookup_head)
-{
-	const NMDedupMultiHeadEntry *head_entry;
-	const LookupEntry *lookup_entry;
-
-	nm_assert (entry);
-
-	G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (LookupEntry, lst_entries_sentinel) == G_STRUCT_OFFSET (NMDedupMultiEntry, lst_entries));
-	G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (NMDedupMultiEntry, lst_entries) == G_STRUCT_OFFSET (NMDedupMultiHeadEntry, lst_entries_head));
-	G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (NMDedupMultiEntry, obj) == G_STRUCT_OFFSET (NMDedupMultiHeadEntry, idx_type));
-	G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (NMDedupMultiEntry, is_head) == G_STRUCT_OFFSET (NMDedupMultiHeadEntry, is_head));
-
-	if (!entry->lst_entries.next) {
-		/* the entry is stack-allocated by _entry_lookup(). */
-		lookup_entry = (LookupEntry *) entry;
-		*out_obj = lookup_entry->obj;
-		*out_idx_type = lookup_entry->idx_type;
-		*out_lookup_head = lookup_entry->lookup_head;
-	} else if (entry->is_head) {
-		head_entry = (NMDedupMultiHeadEntry *) entry;
-		nm_assert (!c_list_is_empty (&head_entry->lst_entries_head));
-		*out_obj = c_list_entry (head_entry->lst_entries_head.next, NMDedupMultiEntry, lst_entries)->obj;
-		*out_idx_type = head_entry->idx_type;
-		*out_lookup_head = TRUE;
-	} else {
-		*out_obj = entry->obj;
-		*out_idx_type = entry->head->idx_type;
-		*out_lookup_head = FALSE;
-	}
-
-	nm_assert (NM_IN_SET (*out_lookup_head, FALSE, TRUE));
-	ASSERT_idx_type (*out_idx_type);
-
-	/* for lookup of the head, we allow to omit object, but only
-	 * if the idx_type does not partition the objects. Otherwise, we
-	 * require a obj to compare. */
-	nm_assert (   !*out_lookup_head
-	           || (   *out_obj
-	               || !(*out_idx_type)->klass->idx_obj_partition_equal));
-
-	/* lookup of the object requires always an object. */
-	nm_assert (   *out_lookup_head
-	           || *out_obj);
-}
-
-static guint
-_dict_idx_entries_hash (const NMDedupMultiEntry *entry)
-{
-	const NMDedupMultiIdxType *idx_type;
-	const NMDedupMultiObj *obj;
-	gboolean lookup_head;
-	NMHashState h;
-
-	_entry_unpack (entry, &idx_type, &obj, &lookup_head);
-
-	nm_hash_init (&h, 1914869417u);
-	if (idx_type->klass->idx_obj_partition_hash_update) {
-		nm_assert (obj);
-		idx_type->klass->idx_obj_partition_hash_update (idx_type, obj, &h);
-	}
-
-	if (!lookup_head)
-		idx_type->klass->idx_obj_id_hash_update (idx_type, obj, &h);
-
-	nm_hash_update_val (&h, idx_type);
-	return nm_hash_complete (&h);
-}
-
-static gboolean
-_dict_idx_entries_equal (const NMDedupMultiEntry *entry_a,
-                         const NMDedupMultiEntry *entry_b)
-{
-	const NMDedupMultiIdxType *idx_type_a, *idx_type_b;
-	const NMDedupMultiObj *obj_a, *obj_b;
-	gboolean lookup_head_a, lookup_head_b;
-
-	_entry_unpack (entry_a, &idx_type_a, &obj_a, &lookup_head_a);
-	_entry_unpack (entry_b, &idx_type_b, &obj_b, &lookup_head_b);
-
-	if (   idx_type_a != idx_type_b
-	    || lookup_head_a != lookup_head_b)
-		return FALSE;
-	if (!nm_dedup_multi_idx_type_partition_equal (idx_type_a, obj_a, obj_b))
-		return FALSE;
-	if (   !lookup_head_a
-	    && !nm_dedup_multi_idx_type_id_equal (idx_type_a, obj_a, obj_b))
-		return FALSE;
-	return TRUE;
-}
-
-/*****************************************************************************/
-
-static gboolean
-_add (NMDedupMultiIndex *self,
-      NMDedupMultiIdxType *idx_type,
-      const NMDedupMultiObj *obj,
-      NMDedupMultiEntry *entry,
-      NMDedupMultiIdxMode mode,
-      const NMDedupMultiEntry *entry_order,
-      NMDedupMultiHeadEntry *head_existing,
-      const NMDedupMultiEntry **out_entry,
-      const NMDedupMultiObj **out_obj_old)
-{
-	NMDedupMultiHeadEntry *head_entry;
-	const NMDedupMultiObj *obj_new, *obj_old;
-	gboolean add_head_entry = FALSE;
-
-	nm_assert (self);
-	ASSERT_idx_type (idx_type);
-	nm_assert (obj);
-	nm_assert (NM_IN_SET (mode,
-	                      NM_DEDUP_MULTI_IDX_MODE_PREPEND,
-	                      NM_DEDUP_MULTI_IDX_MODE_PREPEND_FORCE,
-	                      NM_DEDUP_MULTI_IDX_MODE_APPEND,
-	                      NM_DEDUP_MULTI_IDX_MODE_APPEND_FORCE));
-	nm_assert (!head_existing || head_existing->idx_type == idx_type);
-	nm_assert (({
-	                const NMDedupMultiHeadEntry *_h;
-	                gboolean _ok = TRUE;
-	                if (head_existing) {
-	                    _h = nm_dedup_multi_index_lookup_head (self, idx_type, obj);
-	                    if (head_existing == NM_DEDUP_MULTI_HEAD_ENTRY_MISSING)
-	                        _ok = (_h == NULL);
-	                    else
-	                        _ok = (_h == head_existing);
-	                }
-	                _ok;
-	            }));
-
-	if (entry) {
-		gboolean changed = FALSE;
-
-		nm_dedup_multi_entry_set_dirty (entry, FALSE);
-
-		nm_assert (!head_existing || entry->head == head_existing);
-		nm_assert (!entry_order || entry_order->head == entry->head);
-		nm_assert (!entry_order || c_list_contains (&entry->lst_entries, &entry_order->lst_entries));
-		nm_assert (!entry_order || c_list_contains (&entry_order->lst_entries, &entry->lst_entries));
-
-		switch (mode) {
-		case NM_DEDUP_MULTI_IDX_MODE_PREPEND_FORCE:
-			if (entry_order) {
-				if (nm_c_list_move_before ((CList *) &entry_order->lst_entries, &entry->lst_entries))
-					changed = TRUE;
-			} else {
-				if (nm_c_list_move_front ((CList *) &entry->head->lst_entries_head, &entry->lst_entries))
-					changed = TRUE;
-			}
-			break;
-		case NM_DEDUP_MULTI_IDX_MODE_APPEND_FORCE:
-			if (entry_order) {
-				if (nm_c_list_move_after ((CList *) &entry_order->lst_entries, &entry->lst_entries))
-					changed = TRUE;
-			} else {
-				if (nm_c_list_move_tail ((CList *) &entry->head->lst_entries_head, &entry->lst_entries))
-					changed = TRUE;
-			}
-			break;
-		case NM_DEDUP_MULTI_IDX_MODE_PREPEND:
-		case NM_DEDUP_MULTI_IDX_MODE_APPEND:
-			break;
-		};
-
-		nm_assert (obj->klass == ((const NMDedupMultiObj *) entry->obj)->klass);
-		if (   obj == entry->obj
-		    || obj->klass->obj_full_equal (obj,
-		                                   entry->obj)) {
-			NM_SET_OUT (out_entry, entry);
-			NM_SET_OUT (out_obj_old, nm_dedup_multi_obj_ref (entry->obj));
-			return changed;
-		}
-
-		obj_new = nm_dedup_multi_index_obj_intern (self, obj);
-
-		obj_old = entry->obj;
-		entry->obj = obj_new;
-
-		NM_SET_OUT (out_entry, entry);
-		if (out_obj_old)
-			*out_obj_old = obj_old;
-		else
-			nm_dedup_multi_obj_unref (obj_old);
-		return TRUE;
-	}
-
-	if (    idx_type->klass->idx_obj_partitionable
-	    && !idx_type->klass->idx_obj_partitionable (idx_type, obj)) {
-		/* this object cannot be partitioned by this idx_type. */
-		nm_assert (!head_existing || head_existing == NM_DEDUP_MULTI_HEAD_ENTRY_MISSING);
-		NM_SET_OUT (out_entry, NULL);
-		NM_SET_OUT (out_obj_old, NULL);
-		return FALSE;
-	}
-
-	obj_new = nm_dedup_multi_index_obj_intern (self, obj);
-
-	if (!head_existing)
-		head_entry = _entry_lookup_head (self, idx_type, obj_new);
-	else if (head_existing == NM_DEDUP_MULTI_HEAD_ENTRY_MISSING)
-		head_entry = NULL;
-	else
-		head_entry = head_existing;
-
-	if (!head_entry) {
-		head_entry = g_slice_new0 (NMDedupMultiHeadEntry);
-		head_entry->is_head = TRUE;
-		head_entry->idx_type = idx_type;
-		c_list_init (&head_entry->lst_entries_head);
-		c_list_link_tail (&idx_type->lst_idx_head, &head_entry->lst_idx);
-		add_head_entry = TRUE;
-	} else
-		nm_assert (c_list_contains (&idx_type->lst_idx_head, &head_entry->lst_idx));
-
-	if (entry_order) {
-		nm_assert (!add_head_entry);
-		nm_assert (entry_order->head == head_entry);
-		nm_assert (c_list_contains (&head_entry->lst_entries_head, &entry_order->lst_entries));
-		nm_assert (c_list_contains (&entry_order->lst_entries, &head_entry->lst_entries_head));
-	}
-
-	entry = g_slice_new0 (NMDedupMultiEntry);
-	entry->obj = obj_new;
-	entry->head = head_entry;
-
-	switch (mode) {
-	case NM_DEDUP_MULTI_IDX_MODE_PREPEND:
-	case NM_DEDUP_MULTI_IDX_MODE_PREPEND_FORCE:
-		if (entry_order)
-			c_list_link_before ((CList *) &entry_order->lst_entries, &entry->lst_entries);
-		else
-			c_list_link_front (&head_entry->lst_entries_head, &entry->lst_entries);
-		break;
-	default:
-		if (entry_order)
-			c_list_link_after ((CList *) &entry_order->lst_entries, &entry->lst_entries);
-		else
-			c_list_link_tail (&head_entry->lst_entries_head, &entry->lst_entries);
-		break;
-	};
-
-	idx_type->len++;
-	head_entry->len++;
-
-	if (   add_head_entry
-	    && !g_hash_table_add (self->idx_entries, head_entry))
-		nm_assert_not_reached ();
-
-	if (!g_hash_table_add (self->idx_entries, entry))
-		nm_assert_not_reached ();
-
-	NM_SET_OUT (out_entry, entry);
-	NM_SET_OUT (out_obj_old, NULL);
-	return TRUE;
-}
-
-gboolean
-nm_dedup_multi_index_add (NMDedupMultiIndex *self,
-                          NMDedupMultiIdxType *idx_type,
-                          /*const NMDedupMultiObj * */ gconstpointer obj,
-                          NMDedupMultiIdxMode mode,
-                          const NMDedupMultiEntry **out_entry,
-                          /* const NMDedupMultiObj ** */ gpointer out_obj_old)
-{
-	NMDedupMultiEntry *entry;
-
-	g_return_val_if_fail (self, FALSE);
-	g_return_val_if_fail (idx_type, FALSE);
-	g_return_val_if_fail (obj, FALSE);
-	g_return_val_if_fail (NM_IN_SET (mode,
-	                                 NM_DEDUP_MULTI_IDX_MODE_PREPEND,
-	                                 NM_DEDUP_MULTI_IDX_MODE_PREPEND_FORCE,
-	                                 NM_DEDUP_MULTI_IDX_MODE_APPEND,
-	                                 NM_DEDUP_MULTI_IDX_MODE_APPEND_FORCE),
-	                      FALSE);
-
-	entry = _entry_lookup_obj (self, idx_type, obj);
-	return _add (self, idx_type, obj,
-	             entry, mode,
-	             NULL, NULL,
-	             out_entry, out_obj_old);
-}
-
-/* nm_dedup_multi_index_add_full:
- * @self: the index instance.
- * @idx_type: the index handle for storing @obj.
- * @obj: the NMDedupMultiObj instance to add.
- * @mode: whether to append or prepend the new item. If @entry_order is given,
- *   the entry will be sorted after/before, instead of appending/prepending to
- *   the entire list. If a comparable object is already tracked, then it may
- *   still be resorted by specifying one of the "FORCE" modes.
- * @entry_order: if not NULL, the new entry will be sorted before or after @entry_order.
- *   If given, @entry_order MUST be tracked by @self, and the object it points to MUST
- *   be in the same partition tracked by @idx_type. That is, they must have the same
- *   head_entry and it means, you must ensure that @entry_order and the created/modified
- *   entry will share the same head.
- * @entry_existing: if not NULL, it safes a hash lookup of the entry where the
- *   object will be placed in. You can omit this, and it will be automatically
- *   detected (at the expense of an additional hash lookup).
- *   Basically, this is the result of nm_dedup_multi_index_lookup_obj(),
- *   with the peculiarity that if you know that @obj is not yet tracked,
- *   you may specify %NM_DEDUP_MULTI_ENTRY_MISSING.
- * @head_existing: an optional argument to safe a lookup for the head. If specified,
- *   it must be identical to nm_dedup_multi_index_lookup_head(), with the peculiarity
- *   that if the head is not yet tracked, you may specify %NM_DEDUP_MULTI_HEAD_ENTRY_MISSING
- * @out_entry: if give, return the added entry. This entry may have already exists (update)
- *   or be newly created. If @obj is not partitionable according to @idx_type, @obj
- *   is not to be added and it returns %NULL.
- * @out_obj_old: if given, return the previously contained object. It only
- *   returns a  object, if a matching entry was tracked previously, not if a
- *   new entry was created. Note that when passing @out_obj_old you obtain a reference
- *   to the boxed object and MUST return it with nm_dedup_multi_obj_unref().
- *
- * Adds and object to the index.
- *
- * Return: %TRUE if anything changed, %FALSE if nothing changed.
- */
-gboolean
-nm_dedup_multi_index_add_full (NMDedupMultiIndex *self,
-                               NMDedupMultiIdxType *idx_type,
-                               /*const NMDedupMultiObj * */ gconstpointer obj,
-                               NMDedupMultiIdxMode mode,
-                               const NMDedupMultiEntry *entry_order,
-                               const NMDedupMultiEntry *entry_existing,
-                               const NMDedupMultiHeadEntry *head_existing,
-                               const NMDedupMultiEntry **out_entry,
-                               /* const NMDedupMultiObj ** */ gpointer out_obj_old)
-{
-	NMDedupMultiEntry *entry;
-
-	g_return_val_if_fail (self, FALSE);
-	g_return_val_if_fail (idx_type, FALSE);
-	g_return_val_if_fail (obj, FALSE);
-	g_return_val_if_fail (NM_IN_SET (mode,
-	                                 NM_DEDUP_MULTI_IDX_MODE_PREPEND,
-	                                 NM_DEDUP_MULTI_IDX_MODE_PREPEND_FORCE,
-	                                 NM_DEDUP_MULTI_IDX_MODE_APPEND,
-	                                 NM_DEDUP_MULTI_IDX_MODE_APPEND_FORCE),
-	                      FALSE);
-
-	if (entry_existing == NULL)
-		entry = _entry_lookup_obj (self, idx_type, obj);
-	else if (entry_existing == NM_DEDUP_MULTI_ENTRY_MISSING) {
-		nm_assert (!_entry_lookup_obj (self, idx_type, obj));
-		entry = NULL;
-	} else {
-		nm_assert (entry_existing == _entry_lookup_obj (self, idx_type, obj));
-		entry = (NMDedupMultiEntry *) entry_existing;
-	}
-	return _add (self, idx_type, obj,
-	             entry,
-	             mode, entry_order,
-	             (NMDedupMultiHeadEntry *) head_existing,
-	             out_entry, out_obj_old);
-}
-
-/*****************************************************************************/
-
-static void
-_remove_entry (NMDedupMultiIndex *self,
-               NMDedupMultiEntry *entry,
-               gboolean *out_head_entry_removed)
-{
-	const NMDedupMultiObj *obj;
-	NMDedupMultiHeadEntry *head_entry;
-	NMDedupMultiIdxType *idx_type;
-
-	nm_assert (self);
-	nm_assert (entry);
-	nm_assert (entry->obj);
-	nm_assert (entry->head);
-	nm_assert (!c_list_is_empty (&entry->lst_entries));
-	nm_assert (g_hash_table_lookup (self->idx_entries, entry) == entry);
-
-	head_entry = (NMDedupMultiHeadEntry *) entry->head;
-	obj = entry->obj;
-
-	nm_assert (head_entry);
-	nm_assert (head_entry->len > 0);
-	nm_assert (g_hash_table_lookup (self->idx_entries, head_entry) == head_entry);
-
-	idx_type = (NMDedupMultiIdxType *) head_entry->idx_type;
-	ASSERT_idx_type (idx_type);
-
-	nm_assert (idx_type->len >= head_entry->len);
-	if (--head_entry->len > 0) {
-		nm_assert (idx_type->len > 1);
-		idx_type->len--;
-		head_entry = NULL;
-	}
-
-	NM_SET_OUT (out_head_entry_removed, head_entry != NULL);
-
-	if (!g_hash_table_remove (self->idx_entries, entry))
-		nm_assert_not_reached ();
-
-	if (   head_entry
-	    && !g_hash_table_remove (self->idx_entries, head_entry))
-		nm_assert_not_reached ();
-
-	c_list_unlink_stale (&entry->lst_entries);
-	g_slice_free (NMDedupMultiEntry, entry);
-
-	if (head_entry) {
-		nm_assert (c_list_is_empty (&head_entry->lst_entries_head));
-		c_list_unlink_stale (&head_entry->lst_idx);
-		g_slice_free (NMDedupMultiHeadEntry, head_entry);
-	}
-
-	nm_dedup_multi_obj_unref (obj);
-}
-
-static guint
-_remove_head (NMDedupMultiIndex *self,
-              NMDedupMultiHeadEntry *head_entry,
-              gboolean remove_all /* otherwise just dirty ones */,
-              gboolean mark_survivors_dirty)
-{
-	guint n;
-	gboolean head_entry_removed;
-	CList *iter_entry, *iter_entry_safe;
-
-	nm_assert (self);
-	nm_assert (head_entry);
-	nm_assert (head_entry->len > 0);
-	nm_assert (head_entry->len == c_list_length (&head_entry->lst_entries_head));
-	nm_assert (g_hash_table_lookup (self->idx_entries, head_entry) == head_entry);
-
-	n = 0;
-	c_list_for_each_safe (iter_entry, iter_entry_safe, &head_entry->lst_entries_head) {
-		NMDedupMultiEntry *entry;
-
-		entry = c_list_entry (iter_entry, NMDedupMultiEntry, lst_entries);
-		if (   remove_all
-		    || entry->dirty) {
-			_remove_entry (self,
-			               entry,
-			               &head_entry_removed);
-			n++;
-			if (head_entry_removed)
-				break;
-		} else if (mark_survivors_dirty)
-			nm_dedup_multi_entry_set_dirty (entry, TRUE);
-	}
-
-	return n;
-}
-
-static guint
-_remove_idx_entry (NMDedupMultiIndex *self,
-                   NMDedupMultiIdxType *idx_type,
-                   gboolean remove_all /* otherwise just dirty ones */,
-                   gboolean mark_survivors_dirty)
-{
-	guint n;
-	CList *iter_idx, *iter_idx_safe;
-
-	nm_assert (self);
-	ASSERT_idx_type (idx_type);
-
-	n = 0;
-	c_list_for_each_safe (iter_idx, iter_idx_safe, &idx_type->lst_idx_head) {
-		n += _remove_head (self,
-		                   c_list_entry (iter_idx, NMDedupMultiHeadEntry, lst_idx),
-		                   remove_all, mark_survivors_dirty);
-	}
-	return n;
-}
-
-guint
-nm_dedup_multi_index_remove_entry (NMDedupMultiIndex *self,
-                                   gconstpointer entry)
-{
-	g_return_val_if_fail (self, 0);
-
-	nm_assert (entry);
-
-	if (!((NMDedupMultiEntry *) entry)->is_head) {
-		_remove_entry (self, (NMDedupMultiEntry *) entry, NULL);
-		return 1;
-	}
-	return _remove_head (self, (NMDedupMultiHeadEntry *) entry, TRUE, FALSE);
-}
-
-guint
-nm_dedup_multi_index_remove_obj (NMDedupMultiIndex *self,
-                                 NMDedupMultiIdxType *idx_type,
-                                 /*const NMDedupMultiObj * */ gconstpointer obj,
-                                 /*const NMDedupMultiObj ** */ gconstpointer *out_obj)
-{
-	const NMDedupMultiEntry *entry;
-
-	entry = nm_dedup_multi_index_lookup_obj (self, idx_type, obj);
-	if (!entry) {
-		NM_SET_OUT (out_obj, NULL);
-		return 0;
-	}
-
-	/* since we are about to remove the object, we obviously pass
-	 * a reference to @out_obj, the caller MUST unref the object,
-	 * if he chooses to provide @out_obj. */
-	NM_SET_OUT (out_obj, nm_dedup_multi_obj_ref (entry->obj));
-
-	_remove_entry (self, (NMDedupMultiEntry *) entry, NULL);
-	return 1;
-}
-
-guint
-nm_dedup_multi_index_remove_head (NMDedupMultiIndex *self,
-                                  NMDedupMultiIdxType *idx_type,
-                                  /*const NMDedupMultiObj * */ gconstpointer obj)
-{
-	const NMDedupMultiHeadEntry *entry;
-
-	entry = nm_dedup_multi_index_lookup_head (self, idx_type, obj);
-	return entry
-	       ? _remove_head (self, (NMDedupMultiHeadEntry *) entry, TRUE, FALSE)
-	       : 0;
-}
-
-guint
-nm_dedup_multi_index_remove_idx (NMDedupMultiIndex *self,
-                                 NMDedupMultiIdxType *idx_type)
-{
-	g_return_val_if_fail (self, 0);
-	g_return_val_if_fail (idx_type, 0);
-
-	return _remove_idx_entry (self, idx_type, TRUE, FALSE);
-}
-
-/*****************************************************************************/
-
-/**
- * nm_dedup_multi_index_lookup_obj:
- * @self: the index cache
- * @idx_type: the lookup index type
- * @obj: the object to lookup. This means the match is performed
- *   according to NMDedupMultiIdxTypeClass's idx_obj_id_equal()
- *   of @idx_type.
- *
- * Returns: the cache entry or %NULL if the entry wasn't found.
- */
-const NMDedupMultiEntry *
-nm_dedup_multi_index_lookup_obj (const NMDedupMultiIndex *self,
-                                 const NMDedupMultiIdxType *idx_type,
-                                 /*const NMDedupMultiObj * */ gconstpointer obj)
-{
-	g_return_val_if_fail (self, FALSE);
-	g_return_val_if_fail (idx_type, FALSE);
-	g_return_val_if_fail (obj, FALSE);
-
-	nm_assert (idx_type && idx_type->klass);
-	return _entry_lookup_obj (self, idx_type, obj);
-}
-
-/**
- * nm_dedup_multi_index_lookup_head:
- * @self: the index cache
- * @idx_type: the lookup index type
- * @obj: the object to lookup, of type "const NMDedupMultiObj *".
- *   Depending on the idx_type, you *must* also provide a selector
- *   object, even when looking up the list head. That is, because
- *   the idx_type implementation may choose to partition the objects
- *   in distinct list, so you need a selector object to know which
- *   list head to lookup.
- *
- * Returns: the cache entry or %NULL if the entry wasn't found.
- */
-const NMDedupMultiHeadEntry *
-nm_dedup_multi_index_lookup_head (const NMDedupMultiIndex *self,
-                                  const NMDedupMultiIdxType *idx_type,
-                                  /*const NMDedupMultiObj * */ gconstpointer obj)
-{
-	g_return_val_if_fail (self, FALSE);
-	g_return_val_if_fail (idx_type, FALSE);
-
-	return _entry_lookup_head (self, idx_type, obj);
-}
-
-/*****************************************************************************/
-
-void
-nm_dedup_multi_index_dirty_set_head (NMDedupMultiIndex *self,
-                                     const NMDedupMultiIdxType *idx_type,
-                                     /*const NMDedupMultiObj * */ gconstpointer obj)
-{
-	NMDedupMultiHeadEntry *head_entry;
-	CList *iter_entry;
-
-	g_return_if_fail (self);
-	g_return_if_fail (idx_type);
-
-	head_entry = _entry_lookup_head (self, idx_type, obj);
-	if (!head_entry)
-		return;
-
-	c_list_for_each (iter_entry, &head_entry->lst_entries_head) {
-		NMDedupMultiEntry *entry;
-
-		entry = c_list_entry (iter_entry, NMDedupMultiEntry, lst_entries);
-		nm_dedup_multi_entry_set_dirty (entry, TRUE);
-	}
-}
-
-void
-nm_dedup_multi_index_dirty_set_idx (NMDedupMultiIndex *self,
-                                    const NMDedupMultiIdxType *idx_type)
-{
-	CList *iter_idx, *iter_entry;
-
-	g_return_if_fail (self);
-	g_return_if_fail (idx_type);
-
-	c_list_for_each (iter_idx, &idx_type->lst_idx_head) {
-		NMDedupMultiHeadEntry *head_entry;
-
-		head_entry = c_list_entry (iter_idx, NMDedupMultiHeadEntry, lst_idx);
-		c_list_for_each (iter_entry, &head_entry->lst_entries_head) {
-			NMDedupMultiEntry *entry;
-
-			entry = c_list_entry (iter_entry, NMDedupMultiEntry, lst_entries);
-			nm_dedup_multi_entry_set_dirty (entry, TRUE);
-		}
-	}
-}
-
-/**
- * nm_dedup_multi_index_dirty_remove_idx:
- * @self: the index instance
- * @idx_type: the index-type to select the objects.
- * @mark_survivors_dirty: while the function removes all entries that are
- *   marked as dirty, if @set_dirty is true, the surviving objects
- *   will be marked dirty right away.
- *
- * Deletes all entries for @idx_type that are marked dirty. Only
- * non-dirty objects survive. If @mark_survivors_dirty is set to TRUE, the survivors
- * are marked as dirty right away.
- *
- * Returns: number of deleted entries.
- */
-guint
-nm_dedup_multi_index_dirty_remove_idx (NMDedupMultiIndex *self,
-                                       NMDedupMultiIdxType *idx_type,
-                                       gboolean mark_survivors_dirty)
-{
-	g_return_val_if_fail (self, 0);
-	g_return_val_if_fail (idx_type, 0);
-
-	return _remove_idx_entry (self, idx_type, FALSE, mark_survivors_dirty);
-}
-
-/*****************************************************************************/
-
-static guint
-_dict_idx_objs_hash (const NMDedupMultiObj *obj)
-{
-	NMHashState h;
-
-	nm_hash_init (&h, 1748638583u);
-	obj->klass->obj_full_hash_update (obj, &h);
-	return nm_hash_complete (&h);
-}
-
-static gboolean
-_dict_idx_objs_equal (const NMDedupMultiObj *obj_a,
-                      const NMDedupMultiObj *obj_b)
-{
-	return    obj_a == obj_b
-	       || (   obj_a->klass == obj_b->klass
-	           && obj_a->klass->obj_full_equal (obj_a, obj_b));
-}
-
-void
-nm_dedup_multi_index_obj_release (NMDedupMultiIndex *self,
-                                  /* const NMDedupMultiObj * */ gconstpointer obj)
-{
-	nm_assert (self);
-	nm_assert (obj);
-	nm_assert (g_hash_table_lookup (self->idx_objs, obj) == obj);
-	nm_assert (((const NMDedupMultiObj *) obj)->_multi_idx == self);
-
-	((NMDedupMultiObj *) obj)->_multi_idx = NULL;
-	if (!g_hash_table_remove (self->idx_objs, obj))
-		nm_assert_not_reached ();
-}
-
-gconstpointer
-nm_dedup_multi_index_obj_find (NMDedupMultiIndex *self,
-                               /* const NMDedupMultiObj * */ gconstpointer obj)
-{
-	g_return_val_if_fail (self, NULL);
-	g_return_val_if_fail (obj, NULL);
-
-	return g_hash_table_lookup (self->idx_objs, obj);
-}
-
-gconstpointer
-nm_dedup_multi_index_obj_intern (NMDedupMultiIndex *self,
-                                 /* const NMDedupMultiObj * */ gconstpointer obj)
-{
-	const NMDedupMultiObj *obj_new = obj;
-	const NMDedupMultiObj *obj_old;
-
-	nm_assert (self);
-	nm_assert (obj_new);
-
-	if (obj_new->_multi_idx == self) {
-		nm_assert (g_hash_table_lookup (self->idx_objs, obj_new) == obj_new);
-		nm_dedup_multi_obj_ref (obj_new);
-		return obj_new;
-	}
-
-	obj_old = g_hash_table_lookup (self->idx_objs, obj_new);
-	nm_assert (obj_old != obj_new);
-
-	if (obj_old) {
-		nm_assert (obj_old->_multi_idx == self);
-		nm_dedup_multi_obj_ref (obj_old);
-		return obj_old;
-	}
-
-	if (nm_dedup_multi_obj_needs_clone (obj_new))
-		obj_new = nm_dedup_multi_obj_clone (obj_new);
-	else
-		obj_new = nm_dedup_multi_obj_ref (obj_new);
-
-	nm_assert (obj_new);
-	nm_assert (!obj_new->_multi_idx);
-
-	if (!g_hash_table_add (self->idx_objs, (gpointer) obj_new))
-		nm_assert_not_reached ();
-
-	((NMDedupMultiObj *) obj_new)->_multi_idx = self;
-	return obj_new;
-}
-
-void
-nm_dedup_multi_obj_unref (const NMDedupMultiObj *obj)
-{
-	if (obj) {
-		nm_assert (obj->_ref_count > 0);
-		nm_assert (obj->_ref_count != NM_OBJ_REF_COUNT_STACKINIT);
-
-again:
-		if (--(((NMDedupMultiObj *) obj)->_ref_count) <= 0) {
-			if (obj->_multi_idx) {
-				/* restore the ref-count to 1 and release the object first
-				 * from the index. Then, retry again to unref. */
-				((NMDedupMultiObj *) obj)->_ref_count++;
-				nm_dedup_multi_index_obj_release (obj->_multi_idx, obj);
-				nm_assert (obj->_ref_count == 1);
-				nm_assert (!obj->_multi_idx);
-				goto again;
-			}
-
-			obj->klass->obj_destroy ((NMDedupMultiObj *) obj);
-		}
-	}
-}
-
-gboolean
-nm_dedup_multi_obj_needs_clone (const NMDedupMultiObj *obj)
-{
-	nm_assert (obj);
-
-	if (   obj->_multi_idx
-	    || obj->_ref_count == NM_OBJ_REF_COUNT_STACKINIT)
-		return TRUE;
-
-	if (   obj->klass->obj_needs_clone
-	    && obj->klass->obj_needs_clone (obj))
-		return TRUE;
-
-	return FALSE;
-}
-
-const NMDedupMultiObj *
-nm_dedup_multi_obj_clone (const NMDedupMultiObj *obj)
-{
-	const NMDedupMultiObj *o;
-
-	nm_assert (obj);
-
-	o = obj->klass->obj_clone (obj);
-	nm_assert (o);
-	nm_assert (o->_ref_count == 1);
-	return o;
-}
-
-gconstpointer *
-nm_dedup_multi_objs_to_array_head (const NMDedupMultiHeadEntry *head_entry,
-                                   NMDedupMultiFcnSelectPredicate predicate,
-                                   gpointer user_data,
-                                   guint *out_len)
-{
-	gconstpointer *result;
-	CList *iter;
-	guint i;
-
-	if (!head_entry) {
-		NM_SET_OUT (out_len, 0);
-		return NULL;
-	}
-
-	result = g_new (gconstpointer, head_entry->len + 1);
-	i = 0;
-	c_list_for_each (iter, &head_entry->lst_entries_head) {
-		const NMDedupMultiObj *obj = c_list_entry (iter, NMDedupMultiEntry, lst_entries)->obj;
-
-		if (   !predicate
-		    || predicate (obj, user_data)) {
-			nm_assert (i < head_entry->len);
-			result[i++] = obj;
-		}
-	}
-
-	if (i == 0) {
-		g_free (result);
-		NM_SET_OUT (out_len, 0);
-		return NULL;
-	}
-
-	nm_assert (i <= head_entry->len);
-	NM_SET_OUT (out_len, i);
-	result[i++] = NULL;
-	return result;
-}
-
-GPtrArray *
-nm_dedup_multi_objs_to_ptr_array_head (const NMDedupMultiHeadEntry *head_entry,
-                                       NMDedupMultiFcnSelectPredicate predicate,
-                                       gpointer user_data)
-{
-	GPtrArray *result;
-	CList *iter;
-
-	if (!head_entry)
-		return NULL;
-
-	result = g_ptr_array_new_full (head_entry->len,
-	                               (GDestroyNotify) nm_dedup_multi_obj_unref);
-	c_list_for_each (iter, &head_entry->lst_entries_head) {
-		const NMDedupMultiObj *obj = c_list_entry (iter, NMDedupMultiEntry, lst_entries)->obj;
-
-		if (   !predicate
-		    || predicate (obj, user_data))
-			g_ptr_array_add (result, (gpointer) nm_dedup_multi_obj_ref (obj));
-	}
-
-	if (result->len == 0) {
-		g_ptr_array_unref (result);
-		return NULL;
-	}
-	return result;
-}
-
-/**
- * nm_dedup_multi_entry_reorder:
- * @entry: the entry to reorder. It must not be NULL (and tracked in an index).
- * @entry_order: (allow-none): an optional other entry. It MUST be in the same
- *   list as entry. If given, @entry will be ordered after/before @entry_order.
- *   If left at %NULL, @entry will be moved to the front/end of the list.
- * @order_after: if @entry_order is given, %TRUE means to move @entry after
- *   @entry_order (otherwise before).
- *   If @entry_order is %NULL, %TRUE means to move @entry to the tail of the list
- *   (otherwise the beginning). Note that "tail of the list" here means that @entry
- *   will be linked before the head of the circular list.
- *
- * Returns: %TRUE, if anything was changed. Otherwise, @entry was already at the
- * right place and nothing was done.
- */
-gboolean
-nm_dedup_multi_entry_reorder (const NMDedupMultiEntry *entry,
-                              const NMDedupMultiEntry *entry_order,
-                              gboolean order_after)
-{
-	nm_assert (entry);
-
-	if (!entry_order) {
-		const NMDedupMultiHeadEntry *head_entry = entry->head;
-
-		if (order_after) {
-			if (nm_c_list_move_tail ((CList *) &head_entry->lst_entries_head, (CList *) &entry->lst_entries))
-				return TRUE;
-		} else {
-			if (nm_c_list_move_front ((CList *) &head_entry->lst_entries_head, (CList *) &entry->lst_entries))
-				return TRUE;
-		}
-	} else {
-		if (order_after) {
-			if (nm_c_list_move_after ((CList *) &entry_order->lst_entries, (CList *) &entry->lst_entries))
-				return TRUE;
-		} else {
-			if (nm_c_list_move_before ((CList *) &entry_order->lst_entries, (CList *) &entry->lst_entries))
-				return TRUE;
-		}
-	}
-
-	return FALSE;
-}
-
-/*****************************************************************************/
-
-NMDedupMultiIndex *
-nm_dedup_multi_index_new (void)
-{
-	NMDedupMultiIndex *self;
-
-	self = g_slice_new0 (NMDedupMultiIndex);
-	self->ref_count = 1;
-	self->idx_entries = g_hash_table_new ((GHashFunc) _dict_idx_entries_hash, (GEqualFunc) _dict_idx_entries_equal);
-	self->idx_objs    = g_hash_table_new ((GHashFunc) _dict_idx_objs_hash,    (GEqualFunc) _dict_idx_objs_equal);
-	return self;
-}
-
-NMDedupMultiIndex *
-nm_dedup_multi_index_ref (NMDedupMultiIndex *self)
-{
-	g_return_val_if_fail (self, NULL);
-	g_return_val_if_fail (self->ref_count > 0, NULL);
-
-	self->ref_count++;
-	return self;
-}
-
-NMDedupMultiIndex *
-nm_dedup_multi_index_unref (NMDedupMultiIndex *self)
-{
-	GHashTableIter iter;
-	const NMDedupMultiIdxType *idx_type;
-	NMDedupMultiEntry *entry;
-	const NMDedupMultiObj *obj;
-
-	g_return_val_if_fail (self, NULL);
-	g_return_val_if_fail (self->ref_count > 0, NULL);
-
-	if (--self->ref_count > 0)
-		return NULL;
-
-more:
-	g_hash_table_iter_init (&iter, self->idx_entries);
-	while (g_hash_table_iter_next (&iter, (gpointer *) &entry, NULL)) {
-		if (entry->is_head)
-			idx_type = ((NMDedupMultiHeadEntry *) entry)->idx_type;
-		else
-			idx_type = entry->head->idx_type;
-		_remove_idx_entry (self, (NMDedupMultiIdxType *) idx_type, TRUE, FALSE);
-		goto more;
-	}
-
-	nm_assert (g_hash_table_size (self->idx_entries) == 0);
-
-	g_hash_table_iter_init (&iter, self->idx_objs);
-	while (g_hash_table_iter_next (&iter, (gpointer *) &obj, NULL)) {
-		nm_assert (obj->_multi_idx == self);
-		((NMDedupMultiObj * )obj)->_multi_idx = NULL;
-	}
-	g_hash_table_remove_all (self->idx_objs);
-
-	g_hash_table_unref (self->idx_entries);
-	g_hash_table_unref (self->idx_objs);
-
-	g_slice_free (NMDedupMultiIndex, self);
-	return NULL;
-}
diff --git a/shared/nm-utils/nm-dedup-multi.h b/shared/nm-utils/nm-dedup-multi.h
deleted file mode 100644
index 845b4c3e..00000000
--- a/shared/nm-utils/nm-dedup-multi.h
+++ /dev/null
@@ -1,437 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-/* NetworkManager -- Network link manager
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA.
- *
- * (C) Copyright 2017 Red Hat, Inc.
- */
-
-#ifndef __NM_DEDUP_MULTI_H__
-#define __NM_DEDUP_MULTI_H__
-
-#include "nm-obj.h"
-#include "c-list-util.h"
-
-/*****************************************************************************/
-
-struct _NMHashState;
-
-typedef struct _NMDedupMultiObj             NMDedupMultiObj;
-typedef struct _NMDedupMultiObjClass        NMDedupMultiObjClass;
-typedef struct _NMDedupMultiIdxType         NMDedupMultiIdxType;
-typedef struct _NMDedupMultiIdxTypeClass    NMDedupMultiIdxTypeClass;
-typedef struct _NMDedupMultiEntry           NMDedupMultiEntry;
-typedef struct _NMDedupMultiHeadEntry       NMDedupMultiHeadEntry;
-typedef struct _NMDedupMultiIndex           NMDedupMultiIndex;
-
-typedef enum _NMDedupMultiIdxMode {
-	NM_DEDUP_MULTI_IDX_MODE_PREPEND,
-
-	NM_DEDUP_MULTI_IDX_MODE_PREPEND_FORCE,
-
-	/* append new objects to the end of the list.
-	 * If the object is already in the cache, don't move it. */
-	NM_DEDUP_MULTI_IDX_MODE_APPEND,
-
-	/* like NM_DEDUP_MULTI_IDX_MODE_APPEND, but if the object
-	 * is already in the cache, move it to the end. */
-	NM_DEDUP_MULTI_IDX_MODE_APPEND_FORCE,
-} NMDedupMultiIdxMode;
-
-/*****************************************************************************/
-
-struct _NMDedupMultiObj {
-	union {
-		NMObjBaseInst parent;
-		const NMDedupMultiObjClass *klass;
-	};
-	NMDedupMultiIndex *_multi_idx;
-	guint _ref_count;
-};
-
-struct _NMDedupMultiObjClass {
-	NMObjBaseClass parent;
-
-	const NMDedupMultiObj *(*obj_clone) (const NMDedupMultiObj *obj);
-
-	gboolean (*obj_needs_clone) (const NMDedupMultiObj *obj);
-
-	void (*obj_destroy) (NMDedupMultiObj *obj);
-
-	/* the NMDedupMultiObj can be deduplicated. For that the obj_full_hash_update()
-	 * and obj_full_equal() compare *all* fields of the object, even minor ones. */
-	void (*obj_full_hash_update)  (const NMDedupMultiObj *obj,
-	                               struct _NMHashState *h);
-	gboolean (*obj_full_equal) (const NMDedupMultiObj *obj_a,
-	                            const NMDedupMultiObj *obj_b);
-};
-
-/*****************************************************************************/
-
-static inline const NMDedupMultiObj *
-nm_dedup_multi_obj_ref (const NMDedupMultiObj *obj)
-{
-	/* ref and unref accept const pointers. Objects is supposed to be shared
-	 * and kept immutable. Disallowing to take/return a reference to a const
-	 * NMPObject is cumbersome, because callers are precisely expected to
-	 * keep a ref on the otherwise immutable object. */
-
-	nm_assert (obj);
-	nm_assert (obj->_ref_count != NM_OBJ_REF_COUNT_STACKINIT);
-	nm_assert (obj->_ref_count > 0);
-
-	((NMDedupMultiObj *) obj)->_ref_count++;
-	return obj;
-}
-
-void                   nm_dedup_multi_obj_unref       (const NMDedupMultiObj *obj);
-const NMDedupMultiObj *nm_dedup_multi_obj_clone       (const NMDedupMultiObj *obj);
-gboolean               nm_dedup_multi_obj_needs_clone (const NMDedupMultiObj *obj);
-
-gconstpointer nm_dedup_multi_index_obj_intern (NMDedupMultiIndex *self,
-                                               /* const NMDedupMultiObj * */ gconstpointer obj);
-
-void nm_dedup_multi_index_obj_release (NMDedupMultiIndex *self,
-                                       /* const NMDedupMultiObj * */ gconstpointer obj);
-
-/* const NMDedupMultiObj * */ gconstpointer nm_dedup_multi_index_obj_find (NMDedupMultiIndex *self,
-                                                                           /* const NMDedupMultiObj * */ gconstpointer obj);
-
-/*****************************************************************************/
-
-/* the NMDedupMultiIdxType is an access handle under which you can store and
- * retrieve NMDedupMultiObj instances in NMDedupMultiIndex.
- *
- * The NMDedupMultiIdxTypeClass determines its behavior, but you can have
- * multiple instances (of the same class).
- *
- * For example, NMIP4Config can have idx-type to put there all IPv4 Routes.
- * This idx-type instance is private to the NMIP4Config instance. Basically,
- * the NMIP4Config instance uses the idx-type to maintain an ordered list
- * of routes in NMDedupMultiIndex.
- *
- * However, a NMDedupMultiIdxType may also partition the set of objects
- * in multiple distinct lists. NMIP4Config doesn't do that (because instead
- * of creating one idx-type for IPv4 and IPv6 routes, it just cretaes
- * to distinct idx-types, one for each address family.
- * This partitioning is used by NMPlatform to maintain a lookup index for
- * routes by ifindex. As the ifindex is dynamic, it does not create an
- * idx-type instance for each ifindex. Instead, it has one idx-type for
- * all routes. But whenever accessing NMDedupMultiIndex with an NMDedupMultiObj,
- * the partitioning NMDedupMultiIdxType takes into account the NMDedupMultiObj
- * instance to associate it with the right list.
- *
- * Hence, a NMDedupMultiIdxEntry has a list of possibly multiple NMDedupMultiHeadEntry
- * instances, which each is the head for a list of NMDedupMultiEntry instances.
- * In the platform example, the NMDedupMultiHeadEntry partition the indexed objects
- * by their ifindex. */
-struct _NMDedupMultiIdxType {
-	union {
-		NMObjBaseInst parent;
-		const NMDedupMultiIdxTypeClass *klass;
-	};
-
-	CList lst_idx_head;
-
-	guint len;
-};
-
-void nm_dedup_multi_idx_type_init (NMDedupMultiIdxType *idx_type,
-                                   const NMDedupMultiIdxTypeClass *klass);
-
-struct _NMDedupMultiIdxTypeClass {
-	NMObjBaseClass parent;
-
-	void (*idx_obj_id_hash_update)  (const NMDedupMultiIdxType *idx_type,
-	                                 const NMDedupMultiObj *obj,
-	                                 struct _NMHashState *h);
-	gboolean (*idx_obj_id_equal) (const NMDedupMultiIdxType *idx_type,
-	                              const NMDedupMultiObj *obj_a,
-	                              const NMDedupMultiObj *obj_b);
-
-	/* an NMDedupMultiIdxTypeClass which implements partitioning of the
-	 * tracked objects, must implement the idx_obj_partition*() functions.
-	 *
-	 * idx_obj_partitionable() may return NULL if the object cannot be tracked.
-	 * For example, a index for routes by ifindex, may not want to track any
-	 * routes that don't have a valid ifindex. If the idx-type says that the
-	 * object is not partitionable, it is never added to the NMDedupMultiIndex. */
-	gboolean (*idx_obj_partitionable)   (const NMDedupMultiIdxType *idx_type,
-	                                     const NMDedupMultiObj *obj);
-	void (*idx_obj_partition_hash_update) (const NMDedupMultiIdxType *idx_type,
-	                                       const NMDedupMultiObj *obj,
-	                                       struct _NMHashState *h);
-	gboolean (*idx_obj_partition_equal) (const NMDedupMultiIdxType *idx_type,
-	                                     const NMDedupMultiObj *obj_a,
-	                                     const NMDedupMultiObj *obj_b);
-};
-
-static inline gboolean
-nm_dedup_multi_idx_type_id_equal (const NMDedupMultiIdxType *idx_type,
-                                  /* const NMDedupMultiObj * */ gconstpointer obj_a,
-                                  /* const NMDedupMultiObj * */ gconstpointer obj_b)
-{
-	nm_assert (idx_type);
-	return    obj_a == obj_b
-	       || idx_type->klass->idx_obj_id_equal (idx_type,
-	                                             obj_a,
-	                                             obj_b);
-}
-
-static inline gboolean
-nm_dedup_multi_idx_type_partition_equal (const NMDedupMultiIdxType *idx_type,
-                                         /* const NMDedupMultiObj * */ gconstpointer obj_a,
-                                         /* const NMDedupMultiObj * */ gconstpointer obj_b)
-{
-	nm_assert (idx_type);
-	if (idx_type->klass->idx_obj_partition_equal) {
-		nm_assert (obj_a);
-		nm_assert (obj_b);
-		return    obj_a == obj_b
-		       || idx_type->klass->idx_obj_partition_equal (idx_type,
-		                                                    obj_a,
-		                                                    obj_b);
-	}
-	return TRUE;
-}
-
-/*****************************************************************************/
-
-struct _NMDedupMultiEntry {
-
-	/* this is the list of all entries that share the same head entry.
-	 * All entries compare equal according to idx_obj_partition_equal(). */
-	CList lst_entries;
-
-	/* const NMDedupMultiObj * */ gconstpointer obj;
-
-	bool is_head;
-	bool dirty;
-
-	const NMDedupMultiHeadEntry *head;
-};
-
-struct _NMDedupMultiHeadEntry {
-
-	/* this is the list of all entries that share the same head entry.
-	 * All entries compare equal according to idx_obj_partition_equal(). */
-	CList lst_entries_head;
-
-	const NMDedupMultiIdxType *idx_type;
-
-	bool is_head;
-
-	guint len;
-
-	CList lst_idx;
-};
-
-/*****************************************************************************/
-
-static inline gconstpointer
-nm_dedup_multi_entry_get_obj (const NMDedupMultiEntry *entry)
-{
-	/* convenience method that allows to skip the %NULL check on
-	 * @entry. Think of the NULL-conditional operator ?. of C# */
-	return entry ? entry->obj : NULL;
-}
-
-/*****************************************************************************/
-
-static inline void
-nm_dedup_multi_entry_set_dirty (const NMDedupMultiEntry *entry,
-                                gboolean dirty)
-{
-	/* NMDedupMultiEntry is always exposed as a const object, because it is not
-	 * supposed to be modified outside NMDedupMultiIndex API. Except the "dirty"
-	 * flag. In C++ speak, it is a mutable field.
-	 *
-	 * Add this inline function, to cast-away constness and set the dirty flag. */
-	nm_assert (entry);
-	((NMDedupMultiEntry *) entry)->dirty = dirty;
-}
-
-/*****************************************************************************/
-
-NMDedupMultiIndex *nm_dedup_multi_index_new (void);
-NMDedupMultiIndex *nm_dedup_multi_index_ref (NMDedupMultiIndex *self);
-NMDedupMultiIndex *nm_dedup_multi_index_unref (NMDedupMultiIndex *self);
-
-static inline void
-_nm_auto_unref_dedup_multi_index (NMDedupMultiIndex **v)
-{
-	if (*v)
-		nm_dedup_multi_index_unref (*v);
-}
-#define nm_auto_unref_dedup_multi_index nm_auto(_nm_auto_unref_dedup_multi_index)
-
-#define NM_DEDUP_MULTI_ENTRY_MISSING      ((const NMDedupMultiEntry *)     GUINT_TO_POINTER (1))
-#define NM_DEDUP_MULTI_HEAD_ENTRY_MISSING ((const NMDedupMultiHeadEntry *) GUINT_TO_POINTER (1))
-
-gboolean nm_dedup_multi_index_add_full (NMDedupMultiIndex *self,
-                                        NMDedupMultiIdxType *idx_type,
-                                        /*const NMDedupMultiObj * */ gconstpointer obj,
-                                        NMDedupMultiIdxMode mode,
-                                        const NMDedupMultiEntry *entry_order,
-                                        const NMDedupMultiEntry *entry_existing,
-                                        const NMDedupMultiHeadEntry *head_existing,
-                                        const NMDedupMultiEntry **out_entry,
-                                        /* const NMDedupMultiObj ** */ gpointer out_obj_old);
-
-gboolean nm_dedup_multi_index_add (NMDedupMultiIndex *self,
-                                   NMDedupMultiIdxType *idx_type,
-                                   /*const NMDedupMultiObj * */ gconstpointer obj,
-                                   NMDedupMultiIdxMode mode,
-                                   const NMDedupMultiEntry **out_entry,
-                                   /* const NMDedupMultiObj ** */ gpointer out_obj_old);
-
-const NMDedupMultiEntry *nm_dedup_multi_index_lookup_obj (const NMDedupMultiIndex *self,
-                                                          const NMDedupMultiIdxType *idx_type,
-                                                          /*const NMDedupMultiObj * */ gconstpointer obj);
-
-const NMDedupMultiHeadEntry *nm_dedup_multi_index_lookup_head (const NMDedupMultiIndex *self,
-                                                               const NMDedupMultiIdxType *idx_type,
-                                                               /*const NMDedupMultiObj * */ gconstpointer obj);
-
-guint nm_dedup_multi_index_remove_entry (NMDedupMultiIndex *self,
-                                         gconstpointer entry);
-
-guint nm_dedup_multi_index_remove_obj (NMDedupMultiIndex *self,
-                                       NMDedupMultiIdxType *idx_type,
-                                       /*const NMDedupMultiObj * */ gconstpointer obj,
-                                       /*const NMDedupMultiObj ** */ gconstpointer *out_obj);
-
-guint nm_dedup_multi_index_remove_head (NMDedupMultiIndex *self,
-                                        NMDedupMultiIdxType *idx_type,
-                                        /*const NMDedupMultiObj * */ gconstpointer obj);
-
-guint nm_dedup_multi_index_remove_idx (NMDedupMultiIndex *self,
-                                       NMDedupMultiIdxType *idx_type);
-
-void nm_dedup_multi_index_dirty_set_head (NMDedupMultiIndex *self,
-                                          const NMDedupMultiIdxType *idx_type,
-                                          /*const NMDedupMultiObj * */ gconstpointer obj);
-
-void nm_dedup_multi_index_dirty_set_idx (NMDedupMultiIndex *self,
-                                         const NMDedupMultiIdxType *idx_type);
-
-guint nm_dedup_multi_index_dirty_remove_idx (NMDedupMultiIndex *self,
-                                             NMDedupMultiIdxType *idx_type,
-                                             gboolean mark_survivors_dirty);
-
-/*****************************************************************************/
-
-typedef struct _NMDedupMultiIter {
-	const CList *_head;
-	const CList *_next;
-	const NMDedupMultiEntry *current;
-} NMDedupMultiIter;
-
-static inline void
-nm_dedup_multi_iter_init (NMDedupMultiIter *iter, const NMDedupMultiHeadEntry *head)
-{
-	g_return_if_fail (iter);
-
-	if (head && !c_list_is_empty (&head->lst_entries_head)) {
-		iter->_head = &head->lst_entries_head;
-		iter->_next = head->lst_entries_head.next;
-	} else {
-		iter->_head = NULL;
-		iter->_next = NULL;
-	}
-	iter->current = NULL;
-}
-
-static inline gboolean
-nm_dedup_multi_iter_next (NMDedupMultiIter *iter)
-{
-	g_return_val_if_fail (iter, FALSE);
-
-	if (!iter->_next)
-		return FALSE;
-
-	/* we always look ahead for the next. This way, the user
-	 * may delete the current entry (but no other entries). */
-	iter->current = c_list_entry (iter->_next, NMDedupMultiEntry, lst_entries);
-	if (iter->_next->next == iter->_head)
-		iter->_next = NULL;
-	else
-		iter->_next = iter->_next->next;
-	return TRUE;
-}
-
-#define nm_dedup_multi_iter_for_each(iter, head_entry) \
-	for (nm_dedup_multi_iter_init ((iter), (head_entry)); \
-	     nm_dedup_multi_iter_next ((iter)); \
-	     )
-
-/*****************************************************************************/
-
-typedef gboolean (*NMDedupMultiFcnSelectPredicate) (/* const NMDedupMultiObj * */ gconstpointer obj,
-                                                    gpointer user_data);
-
-gconstpointer *nm_dedup_multi_objs_to_array_head (const NMDedupMultiHeadEntry *head_entry,
-                                                  NMDedupMultiFcnSelectPredicate predicate,
-                                                  gpointer user_data,
-                                                  guint *out_len);
-GPtrArray *nm_dedup_multi_objs_to_ptr_array_head (const NMDedupMultiHeadEntry *head_entry,
-                                                  NMDedupMultiFcnSelectPredicate predicate,
-                                                  gpointer user_data);
-
-static inline const NMDedupMultiEntry *
-nm_dedup_multi_head_entry_get_idx (const NMDedupMultiHeadEntry *head_entry,
-                                   int idx)
-{
-	CList *iter;
-
-	if (head_entry) {
-		if (idx >= 0) {
-			c_list_for_each (iter, &head_entry->lst_entries_head) {
-				if (idx-- == 0)
-					return c_list_entry (iter, NMDedupMultiEntry, lst_entries);
-			}
-		} else {
-			for (iter = head_entry->lst_entries_head.prev;
-			     iter != &head_entry->lst_entries_head;
-			     iter = iter->prev) {
-				if (++idx == 0)
-					return c_list_entry (iter, NMDedupMultiEntry, lst_entries);
-			}
-		}
-	}
-	return NULL;
-}
-
-static inline void
-nm_dedup_multi_head_entry_sort (const NMDedupMultiHeadEntry *head_entry,
-                                CListSortCmp cmp,
-                                gconstpointer user_data)
-{
-	if (head_entry) {
-		/* the head entry can be sorted directly without messing up the
-		 * index to which it belongs. Of course, this does mess up any
-		 * NMDedupMultiIter instances. */
-		c_list_sort ((CList *) &head_entry->lst_entries_head, cmp, user_data);
-	}
-}
-
-gboolean nm_dedup_multi_entry_reorder (const NMDedupMultiEntry *entry,
-                                       const NMDedupMultiEntry *entry_order,
-                                       gboolean order_after);
-
-/*****************************************************************************/
-
-#endif /* __NM_DEDUP_MULTI_H__ */
diff --git a/shared/nm-utils/nm-enum-utils.c b/shared/nm-utils/nm-enum-utils.c
deleted file mode 100644
index a4f6e809..00000000
--- a/shared/nm-utils/nm-enum-utils.c
+++ /dev/null
@@ -1,372 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-/* NetworkManager -- Network link manager
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA.
- *
- * (C) Copyright 2017 Red Hat, Inc.
- */
-
-#include "nm-default.h"
-
-#include "nm-enum-utils.h"
-
-/*****************************************************************************/
-
-#define IS_FLAGS_SEPARATOR(ch)  (NM_IN_SET ((ch), ' ', '\t', ',', '\n', '\r'))
-
-static void
-_ASSERT_enum_values_info (GType type,
-                          const NMUtilsEnumValueInfo *value_infos)
-{
-#if NM_MORE_ASSERTS > 5
-	nm_auto_unref_gtypeclass GTypeClass *klass = NULL;
-	gs_unref_hashtable GHashTable *ht = NULL;
-
-	klass = g_type_class_ref (type);
-
-	g_assert (G_IS_ENUM_CLASS (klass) || G_IS_FLAGS_CLASS (klass));
-
-	if (!value_infos)
-		return;
-
-	ht = g_hash_table_new (g_str_hash, g_str_equal);
-
-	for (; value_infos->nick; value_infos++) {
-
-		g_assert (value_infos->nick[0]);
-
-		/* duplicate nicks make no sense!! */
-		g_assert (!g_hash_table_contains (ht, value_infos->nick));
-		g_hash_table_add (ht, (gpointer) value_infos->nick);
-
-		if (G_IS_ENUM_CLASS (klass)) {
-			GEnumValue *enum_value;
-
-			enum_value = g_enum_get_value_by_nick (G_ENUM_CLASS (klass), value_infos->nick);
-			if (enum_value) {
-				/* we do allow specifying the same name via @value_infos and @type.
-				 * That might make sense, if @type comes from a library where older versions
-				 * of the library don't yet support the value. In this case, the caller can
-				 * provide the nick via @value_infos, to support the older library version.
-				 * And then, when actually running against a newer library version where
-				 * @type knows the nick, we have this situation.
-				 *
-				 * Another reason for specifying a nick both in @value_infos and @type,
-				 * is to specify an alias which is not used with highest preference. For
-				 * example, if you add an alias "disabled" for "none" (both numerically
-				 * equal), then the first alias in @value_infos will be preferred over
-				 * the name from @type. So, to still use "none" as preferred name, you may
-				 * explicitly specify the "none" alias in @value_infos before "disabled".
-				 *
-				 * However, what never is allowed, is to use a name (nick) to re-number
-				 * the value. That is, if both @value_infos and @type contain a particular
-				 * nick, their numeric values must agree as well.
-				 * Allowing this, would be very confusing, because the name would have a different
-				 * value from the regular GLib GEnum API.
-				 */
-				g_assert (enum_value->value == value_infos->value);
-			}
-		} else {
-			GFlagsValue *flags_value;
-
-			flags_value = g_flags_get_value_by_nick (G_FLAGS_CLASS (klass), value_infos->nick);
-			if (flags_value) {
-				/* see ENUM case above. */
-				g_assert (flags_value->value == (guint) value_infos->value);
-			}
-		}
-	}
-#endif
-}
-
-static gboolean
-_is_hex_string (const char *str)
-{
-	return    str[0] == '0'
-	       && str[1] == 'x'
-	       && str[2]
-	       && NM_STRCHAR_ALL (&str[2], ch, g_ascii_isxdigit (ch));
-}
-
-static gboolean
-_is_dec_string (const char *str)
-{
-	return    str[0]
-	       && NM_STRCHAR_ALL (&str[0], ch, g_ascii_isdigit (ch));
-}
-
-static gboolean
-_enum_is_valid_enum_nick (const char *str)
-{
-	return    str[0]
-	       && !NM_STRCHAR_ANY (str, ch, g_ascii_isspace (ch))
-	       && !_is_dec_string (str)
-	       && !_is_hex_string (str);
-}
-
-static gboolean
-_enum_is_valid_flags_nick (const char *str)
-{
-	return    str[0]
-	       && !NM_STRCHAR_ANY (str, ch, IS_FLAGS_SEPARATOR (ch))
-	       && !_is_dec_string (str)
-	       && !_is_hex_string (str);
-}
-
-char *
-_nm_utils_enum_to_str_full (GType type,
-                            int value,
-                            const char *flags_separator,
-                            const NMUtilsEnumValueInfo *value_infos)
-{
-	nm_auto_unref_gtypeclass GTypeClass *klass = NULL;
-
-	_ASSERT_enum_values_info (type, value_infos);
-
-	if (   flags_separator
-	    && (   !flags_separator[0]
-	        || NM_STRCHAR_ANY (flags_separator, ch, !IS_FLAGS_SEPARATOR (ch))))
-		g_return_val_if_reached (NULL);
-
-	klass = g_type_class_ref (type);
-
-	if (G_IS_ENUM_CLASS (klass)) {
-		GEnumValue *enum_value;
-
-		for ( ; value_infos && value_infos->nick; value_infos++) {
-			if (value_infos->value == value)
-				return g_strdup (value_infos->nick);
-		}
-
-		enum_value = g_enum_get_value (G_ENUM_CLASS (klass), value);
-		if (   !enum_value
-		    || !_enum_is_valid_enum_nick (enum_value->value_nick))
-			return g_strdup_printf ("%d", value);
-		else
-			return g_strdup (enum_value->value_nick);
-	} else if (G_IS_FLAGS_CLASS (klass)) {
-		GFlagsValue *flags_value;
-		GString *str = g_string_new ("");
-		unsigned uvalue = (unsigned) value;
-
-		flags_separator = flags_separator ?: " ";
-
-		for ( ; value_infos && value_infos->nick; value_infos++) {
-
-			nm_assert (_enum_is_valid_flags_nick (value_infos->nick));
-
-			if (uvalue == 0) {
-				if (value_infos->value != 0)
-					continue;
-			} else {
-				if (!NM_FLAGS_ALL (uvalue, (unsigned) value_infos->value))
-					continue;
-			}
-
-			if (str->len)
-				g_string_append (str, flags_separator);
-			g_string_append (str, value_infos->nick);
-			uvalue &= ~((unsigned) value_infos->value);
-			if (uvalue == 0) {
-				/* we printed all flags. Done. */
-				goto flags_done;
-			}
-		}
-
-		do {
-			flags_value = g_flags_get_first_value (G_FLAGS_CLASS (klass), uvalue);
-			if (str->len)
-				g_string_append (str, flags_separator);
-			if (   !flags_value
-			    || !_enum_is_valid_flags_nick (flags_value->value_nick)) {
-				if (uvalue)
-					g_string_append_printf (str, "0x%x", uvalue);
-				break;
-			}
-			g_string_append (str, flags_value->value_nick);
-			uvalue &= ~flags_value->value;
-		} while (uvalue);
-
-flags_done:
-		return g_string_free (str, FALSE);
-	}
-
-	g_return_val_if_reached (NULL);
-}
-
-static const NMUtilsEnumValueInfo *
-_find_value_info (const NMUtilsEnumValueInfo *value_infos, const char *needle)
-{
-	if (value_infos) {
-		for (; value_infos->nick; value_infos++) {
-			if (nm_streq (needle, value_infos->nick))
-				return value_infos;
-		}
-	}
-	return NULL;
-}
-
-gboolean
-_nm_utils_enum_from_str_full (GType type,
-                              const char *str,
-                              int *out_value,
-                              char **err_token,
-                              const NMUtilsEnumValueInfo *value_infos)
-{
-	GTypeClass *klass;
-	gboolean ret = FALSE;
-	int value = 0;
-	gs_free char *str_clone = NULL;
-	char *s;
-	gint64 v64;
-	const NMUtilsEnumValueInfo *nick;
-
-	g_return_val_if_fail (str, FALSE);
-
-	_ASSERT_enum_values_info (type, value_infos);
-
-	str_clone = strdup (str);
-	s = nm_str_skip_leading_spaces (str_clone);
-	g_strchomp (s);
-
-	klass = g_type_class_ref (type);
-
-	if (G_IS_ENUM_CLASS (klass)) {
-		GEnumValue *enum_value;
-
-		if (s[0]) {
-			if (_is_hex_string (s)) {
-				v64 = _nm_utils_ascii_str_to_int64 (s, 16, 0, G_MAXUINT, -1);
-				if (v64 != -1) {
-					value = (int) v64;
-					ret = TRUE;
-				}
-			} else if (_is_dec_string (s)) {
-				v64 = _nm_utils_ascii_str_to_int64 (s, 10, 0, G_MAXUINT, -1);
-				if (v64 != -1) {
-					value = (int) v64;
-					ret = TRUE;
-				}
-			} else if ((nick = _find_value_info (value_infos, s))) {
-				value = nick->value;
-				ret = TRUE;
-			} else if ((enum_value = g_enum_get_value_by_nick (G_ENUM_CLASS (klass), s))) {
-				value = enum_value->value;
-				ret = TRUE;
-			}
-		}
-	} else if (G_IS_FLAGS_CLASS (klass)) {
-		GFlagsValue *flags_value;
-		unsigned uvalue = 0;
-
-		ret = TRUE;
-		while (s[0]) {
-			char *s_end;
-
-			for (s_end = s; s_end[0]; s_end++) {
-				if (IS_FLAGS_SEPARATOR (s_end[0])) {
-					s_end[0] = '\0';
-					s_end++;
-					break;
-				}
-			}
-
-			if (s[0]) {
-				if (_is_hex_string (s)) {
-					v64 = _nm_utils_ascii_str_to_int64 (&s[2], 16, 0, G_MAXUINT, -1);
-					if (v64 == -1) {
-						ret = FALSE;
-						break;
-					}
-					uvalue |= (unsigned) v64;
-				} else if (_is_dec_string (s)) {
-					v64 = _nm_utils_ascii_str_to_int64 (s, 10, 0, G_MAXUINT, -1);
-					if (v64 == -1) {
-						ret = FALSE;
-						break;
-					}
-					uvalue |= (unsigned) v64;
-				} else if ((nick = _find_value_info (value_infos, s)))
-					uvalue |= (unsigned) nick->value;
-				else if ((flags_value = g_flags_get_value_by_nick (G_FLAGS_CLASS (klass), s)))
-					uvalue |= flags_value->value;
-				else {
-					ret = FALSE;
-					break;
-				}
-			}
-
-			s = s_end;
-		}
-
-		value = (int) uvalue;
-	} else
-		g_return_val_if_reached (FALSE);
-
-	NM_SET_OUT (err_token, !ret && s[0] ? g_strdup (s) : NULL);
-	NM_SET_OUT (out_value, ret ? value : 0);
-	g_type_class_unref (klass);
-	return ret;
-}
-
-const char **
-_nm_utils_enum_get_values (GType type, int from, int to)
-{
-	GTypeClass *klass;
-	GPtrArray *array;
-	int i;
-	char sbuf[64];
-
-	klass = g_type_class_ref (type);
-	array = g_ptr_array_new ();
-
-	if (G_IS_ENUM_CLASS (klass)) {
-		GEnumClass *enum_class = G_ENUM_CLASS (klass);
-		GEnumValue *enum_value;
-
-		for (i = 0; i < enum_class->n_values; i++) {
-			enum_value = &enum_class->values[i];
-			if (enum_value->value >= from && enum_value->value <= to) {
-				if (_enum_is_valid_enum_nick (enum_value->value_nick))
-					g_ptr_array_add (array, (gpointer) enum_value->value_nick);
-				else
-					g_ptr_array_add (array, (gpointer) g_intern_string (nm_sprintf_buf (sbuf, "%d", enum_value->value)));
-			}
-		}
-	} else if (G_IS_FLAGS_CLASS (klass)) {
-		GFlagsClass *flags_class = G_FLAGS_CLASS (klass);
-		GFlagsValue *flags_value;
-
-		for (i = 0; i < flags_class->n_values; i++) {
-			flags_value = &flags_class->values[i];
-			if (flags_value->value >= (guint) from && flags_value->value <= (guint) to) {
-				if (_enum_is_valid_flags_nick (flags_value->value_nick))
-					g_ptr_array_add (array, (gpointer) flags_value->value_nick);
-				else
-					g_ptr_array_add (array, (gpointer) g_intern_string (nm_sprintf_buf (sbuf, "0x%x", (unsigned) flags_value->value)));
-			}
-		}
-	} else {
-		g_type_class_unref (klass);
-		g_ptr_array_free (array, TRUE);
-		g_return_val_if_reached (NULL);
-	}
-
-	g_type_class_unref (klass);
-	g_ptr_array_add (array, NULL);
-
-	return (const char **) g_ptr_array_free (array, FALSE);
-}
diff --git a/shared/nm-utils/nm-enum-utils.h b/shared/nm-utils/nm-enum-utils.h
deleted file mode 100644
index 1827fdf4..00000000
--- a/shared/nm-utils/nm-enum-utils.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-/* NetworkManager -- Network link manager
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA.
- *
- * (C) Copyright 2017 Red Hat, Inc.
- */
-
-#ifndef __NM_ENUM_UTILS_H__
-#define __NM_ENUM_UTILS_H__
-
-/*****************************************************************************/
-
-typedef struct _NMUtilsEnumValueInfo {
-	/* currently, this is only used for _nm_utils_enum_from_str_full() to
-	 * declare additional aliases for values. */
-	const char *nick;
-	int value;
-} NMUtilsEnumValueInfo;
-
-char *_nm_utils_enum_to_str_full (GType type,
-                                  int value,
-                                  const char *sep,
-                                  const NMUtilsEnumValueInfo *value_infos);
-gboolean _nm_utils_enum_from_str_full (GType type,
-                                       const char *str,
-                                       int *out_value,
-                                       char **err_token,
-                                       const NMUtilsEnumValueInfo *value_infos);
-
-const char **_nm_utils_enum_get_values (GType type, int from, int to);
-
-/*****************************************************************************/
-
-#endif /* __NM_ENUM_UTILS_H__ */
diff --git a/shared/nm-utils/nm-errno.c b/shared/nm-utils/nm-errno.c
deleted file mode 100644
index 30eb9a8e..00000000
--- a/shared/nm-utils/nm-errno.c
+++ /dev/null
@@ -1,198 +0,0 @@
-/* NetworkManager -- Network link manager
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA.
- *
- * Copyright 2018 Red Hat, Inc.
- */
-
-#include "nm-default.h"
-
-#include "nm-errno.h"
-
-#include <pthread.h>
-
-/*****************************************************************************/
-
-NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_geterror,
-#if 0
-	enum _NMErrno,
-#else
-	int,
-#endif
-	NM_UTILS_LOOKUP_DEFAULT (NULL),
-
-	NM_UTILS_LOOKUP_STR_ITEM (NME_ERRNO_SUCCESS,      "NME_ERRNO_SUCCESS"),
-	NM_UTILS_LOOKUP_STR_ITEM (NME_ERRNO_OUT_OF_RANGE, "NME_ERRNO_OUT_OF_RANGE"),
-
-	NM_UTILS_LOOKUP_STR_ITEM (NME_UNSPEC,             "NME_UNSPEC"),
-	NM_UTILS_LOOKUP_STR_ITEM (NME_BUG,                "NME_BUG"),
-	NM_UTILS_LOOKUP_STR_ITEM (NME_NATIVE_ERRNO,       "NME_NATIVE_ERRNO"),
-
-	NM_UTILS_LOOKUP_STR_ITEM (NME_NL_ATTRSIZE,        "NME_NL_ATTRSIZE"),
-	NM_UTILS_LOOKUP_STR_ITEM (NME_NL_BAD_SOCK,        "NME_NL_BAD_SOCK"),
-	NM_UTILS_LOOKUP_STR_ITEM (NME_NL_DUMP_INTR,       "NME_NL_DUMP_INTR"),
-	NM_UTILS_LOOKUP_STR_ITEM (NME_NL_MSG_OVERFLOW,    "NME_NL_MSG_OVERFLOW"),
-	NM_UTILS_LOOKUP_STR_ITEM (NME_NL_MSG_TOOSHORT,    "NME_NL_MSG_TOOSHORT"),
-	NM_UTILS_LOOKUP_STR_ITEM (NME_NL_MSG_TRUNC,       "NME_NL_MSG_TRUNC"),
-	NM_UTILS_LOOKUP_STR_ITEM (NME_NL_SEQ_MISMATCH,    "NME_NL_SEQ_MISMATCH"),
-	NM_UTILS_LOOKUP_STR_ITEM (NME_NL_NOADDR,          "NME_NL_NOADDR"),
-
-	NM_UTILS_LOOKUP_STR_ITEM (NME_PL_NOT_FOUND,       "not-found"),
-	NM_UTILS_LOOKUP_STR_ITEM (NME_PL_EXISTS,          "exists"),
-	NM_UTILS_LOOKUP_STR_ITEM (NME_PL_WRONG_TYPE,      "wrong-type"),
-	NM_UTILS_LOOKUP_STR_ITEM (NME_PL_NOT_SLAVE,       "not-slave"),
-	NM_UTILS_LOOKUP_STR_ITEM (NME_PL_NO_FIRMWARE,     "no-firmware"),
-	NM_UTILS_LOOKUP_STR_ITEM (NME_PL_OPNOTSUPP,       "not-supported"),
-	NM_UTILS_LOOKUP_STR_ITEM (NME_PL_NETLINK,         "netlink"),
-	NM_UTILS_LOOKUP_STR_ITEM (NME_PL_CANT_SET_MTU,    "cant-set-mtu"),
-
-	NM_UTILS_LOOKUP_ITEM_IGNORE (_NM_ERRNO_MININT),
-	NM_UTILS_LOOKUP_ITEM_IGNORE (_NM_ERRNO_RESERVED_LAST_PLUS_1),
-);
-
-/**
- * nm_strerror():
- * @nmerr: the NetworkManager specific errno to be converted
- *   to string.
- *
- * NetworkManager specific error numbers reserve a range in "errno.h" with
- * our own defines. For numbers that don't fall into this range, the numbers
- * are identical to the common error numbers.
- *
- * Idential to strerror(), g_strerror(), nm_strerror_native() for error numbers
- * that are not in the reserved range of NetworkManager specific errors.
- *
- * Returns: (transfer none): the string representation of the error number.
- */
-const char *
-nm_strerror (int nmerr)
-{
-	const char *s;
-
-	nmerr = nm_errno (nmerr);
-
-	if (nmerr >= _NM_ERRNO_RESERVED_FIRST) {
-		s = _geterror (nmerr);
-		if (s)
-			return s;
-	}
-	return nm_strerror_native (nmerr);
-}
-
-/*****************************************************************************/
-
-/**
- * nm_strerror_native_r:
- * @errsv: the errno to convert to string.
- * @buf: the output buffer where to write the string to.
- * @buf_size: the length of buffer.
- *
- * This is like strerror_r(), with one difference: depending on the
- * locale, the returned string is guaranteed to be valid UTF-8.
- * Also, there is some confusion as to whether to use glibc's
- * strerror_r() or the POXIX/XSI variant. This is abstracted
- * by the function.
- *
- * Note that the returned buffer may also be a statically allocated
- * buffer, and not the input buffer @buf. Consequently, the returned
- * string may be longer than @buf_size.
- *
- * Returns: (transfer none): a NUL terminated error message. This is either a static
- *   string (that is never freed), or the provided @buf argumnt.
- */
-const char *
-nm_strerror_native_r (int errsv, char *buf, gsize buf_size)
-{
-	char *buf2;
-
-	nm_assert (buf);
-	nm_assert (buf_size > 0);
-
-#if (_POSIX_C_SOURCE >= 200112L) && !  _GNU_SOURCE
-	/* XSI-compliant */
-	{
-		int errno_saved = errno;
-
-		if (strerror_r (errsv, buf, buf_size) != 0) {
-			g_snprintf (buf, buf_size, "Unspecified errno %d", errsv);
-			errno = errno_saved;
-		}
-		buf2 = buf;
-	}
-#else
-	/* GNU-specific */
-	buf2 = strerror_r (errsv, buf, buf_size);
-#endif
-
-	/* like g_strerror(), ensure that the error message is UTF-8. */
-	if (   !g_get_charset (NULL)
-	    && !g_utf8_validate (buf2, -1, NULL)) {
-		gs_free char *msg = NULL;
-
-		msg = g_locale_to_utf8 (buf2, -1, NULL, NULL, NULL);
-		if (msg) {
-			g_strlcpy (buf, msg, buf_size);
-			buf2 = buf;
-		}
-	}
-
-	return buf2;
-}
-
-/**
- * nm_strerror_native:
- * @errsv: the errno integer from <errno.h>
- *
- * Like strerror(), but strerror() is not thread-safe and not guaranteed
- * to be UTF-8.
- *
- * g_strerror() is a thread-safe variant of strerror(), however it caches
- * all returned strings in a dictionary. That means, using this on untrusted
- * error numbers can result in this cache to grow without limits.
- *
- * Instead, return a tread-local buffer. This way, it's thread-safe.
- *
- * There is a downside to this: subsequent calls of nm_strerror_native()
- * overwrite the error message.
- *
- * Returns: (transfer none): the text representation of the error number.
- */
-const char *
-nm_strerror_native (int errsv)
-{
-	static _nm_thread_local char *buf_static = NULL;
-	char *buf;
-
-	buf = buf_static;
-	if (G_UNLIKELY (!buf)) {
-		int errno_saved = errno;
-		pthread_key_t key;
-
-		buf = g_malloc (NM_STRERROR_BUFSIZE);
-		buf_static = buf;
-
-		if (   pthread_key_create (&key, g_free) != 0
-		    || pthread_setspecific (key, buf) != 0) {
-			/* Failure. We will leak the buffer when the thread exits.
-			 *
-			 * Nothing we can do about it really. For Debug builds we fail with an assertion. */
-			nm_assert_not_reached ();
-		}
-		errno = errno_saved;
-	}
-
-	return nm_strerror_native_r (errsv, buf, NM_STRERROR_BUFSIZE);
-}
diff --git a/shared/nm-utils/nm-errno.h b/shared/nm-utils/nm-errno.h
deleted file mode 100644
index d77735a7..00000000
--- a/shared/nm-utils/nm-errno.h
+++ /dev/null
@@ -1,185 +0,0 @@
-/* NetworkManager -- Network link manager
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA.
- *
- * Copyright 2018 Red Hat, Inc.
- */
-
-#ifndef __NM_ERRNO_H__
-#define __NM_ERRNO_H__
-
-#include <errno.h>
-
-/*****************************************************************************/
-
-enum _NMErrno {
-	_NM_ERRNO_MININT         = G_MININT,
-	_NM_ERRNO_MAXINT         = G_MAXINT,
-	_NM_ERRNO_RESERVED_FIRST = 100000,
-
-
-	/* when we cannot represent a number as positive number, we resort to this
-	 * number. Basically, the values G_MININT, -NME_ERRNO_SUCCESS, NME_ERRNO_SUCCESS
-	 * and G_MAXINT all map to the same value. */
-	NME_ERRNO_OUT_OF_RANGE   = G_MAXINT,
-
-	/* Indicate that the original errno was zero. Zero denotes *no error*, but we know something
-	 * went wrong and we want to report some error. This is a placeholder to mean, something
-	 * was wrong, but errno was zero. */
-	NME_ERRNO_SUCCESS        = G_MAXINT - 1,
-
-
-	/* an unspecified error. */
-	NME_UNSPEC = _NM_ERRNO_RESERVED_FIRST,
-
-	/* A bug, for example when an assertion failed.
-	 * Should never happen. */
-	NME_BUG,
-
-	/* a native error number (from <errno.h>) cannot be mapped as
-	 * an nm-error, because it is in the range [_NM_ERRNO_RESERVED_FIRST,
-	 * _NM_ERRNO_RESERVED_LAST]. */
-	NME_NATIVE_ERRNO,
-
-	/* netlink errors. */
-	NME_NL_SEQ_MISMATCH,
-	NME_NL_MSG_TRUNC,
-	NME_NL_MSG_TOOSHORT,
-	NME_NL_DUMP_INTR,
-	NME_NL_ATTRSIZE,
-	NME_NL_BAD_SOCK,
-	NME_NL_NOADDR,
-	NME_NL_MSG_OVERFLOW,
-
-	/* platform errors. */
-	NME_PL_NOT_FOUND,
-	NME_PL_EXISTS,
-	NME_PL_WRONG_TYPE,
-	NME_PL_NOT_SLAVE,
-	NME_PL_NO_FIRMWARE,
-	NME_PL_OPNOTSUPP,
-	NME_PL_NETLINK,
-	NME_PL_CANT_SET_MTU,
-
-	_NM_ERRNO_RESERVED_LAST_PLUS_1,
-	_NM_ERRNO_RESERVED_LAST = _NM_ERRNO_RESERVED_LAST_PLUS_1 - 1,
-};
-
-/*****************************************************************************/
-
-/* When we receive an errno from a system function, we can safely assume
- * that the error number is not negative. We rely on that, and possibly just
- * "return -errsv;" to signal an error. We also rely on that, because libc
- * is our trusted base: meaning, if it cannot even succeed at setting errno
- * according to specification, all bets are off.
- *
- * This macro returns the input argument, and asserts that the error variable
- * is positive.
- *
- * In a sense, the macro is related to nm_errno_native() function, but the difference
- * is that this macro asserts that @errsv is positive, while nm_errno_native() coerces
- * negative values to be non-negative. */
-#define NM_ERRNO_NATIVE(errsv) \
-	({ \
-		const int _errsv_x = (errsv); \
-		\
-		nm_assert (_errsv_x > 0); \
-		_errsv_x; \
-	})
-
-/* Normalize native errno.
- *
- * Our API may return native error codes (<errno.h>) as negative values. This function
- * takes such an errno, and normalizes it to their positive value.
- *
- * The special values G_MININT and zero are coerced to NME_ERRNO_OUT_OF_RANGE and NME_ERRNO_SUCCESS
- * respectively.
- * Other values are coerced to their inverse.
- * Other positive values are returned unchanged.
- *
- * Basically, this normalizes errsv to be positive (taking care of two pathological cases).
- */
-static inline int
-nm_errno_native (int errsv)
-{
-	switch (errsv) {
-	case 0:                  return NME_ERRNO_SUCCESS;
-	case G_MININT:           return NME_ERRNO_OUT_OF_RANGE;
-	default:
-		return errsv >= 0 ? errsv : -errsv;
-	}
-}
-
-/* Normalizes an nm-error to be positive.
- *
- * Various API returns negative error codes, and this function converts the negative
- * value to its positive.
- *
- * Note that @nmerr is on the domain of NetworkManager specific error numbers,
- * which is not the same as the native error numbers (errsv from <errno.h>). But
- * as far as normalizing goes, nm_errno() does exactly the same remapping as
- * nm_errno_native(). */
-static inline int
-nm_errno (int nmerr)
-{
-	return nm_errno_native (nmerr);
-}
-
-/* this maps a native errno to a (always non-negative) nm-error number.
- *
- * Note that nm-error numbers are embedded into the range of regular
- * errno. The only difference is, that nm-error numbers reserve a
- * range (_NM_ERRNO_RESERVED_FIRST, _NM_ERRNO_RESERVED_LAST) for their
- * own purpose.
- *
- * That means, converting an errno to nm-error number means in
- * most cases just returning itself.
- * Only pathological cases need special handling:
- *
- *  - 0 is mapped to NME_ERRNO_SUCCESS;
- *  - G_MININT is mapped to NME_ERRNO_OUT_OF_RANGE;
- *  - values in the range of (+/-) [_NM_ERRNO_RESERVED_FIRST, _NM_ERRNO_RESERVED_LAST]
- *    are mapped to NME_NATIVE_ERRNO
- *  - all other values are their (positive) absolute value.
- */
-static inline int
-nm_errno_from_native (int errsv)
-{
-	switch (errsv) {
-	case 0:                  return NME_ERRNO_SUCCESS;
-	case G_MININT:           return NME_ERRNO_OUT_OF_RANGE;
-	default:
-		if (errsv < 0)
-			errsv = -errsv;
-		return   G_UNLIKELY (   errsv >= _NM_ERRNO_RESERVED_FIRST
-		                     && errsv <= _NM_ERRNO_RESERVED_LAST)
-		       ? NME_NATIVE_ERRNO
-		       : errsv;
-	}
-}
-
-const char *nm_strerror (int nmerr);
-
-/*****************************************************************************/
-
-#define NM_STRERROR_BUFSIZE 1024
-
-const char *nm_strerror_native_r (int errsv, char *buf, gsize buf_size);
-const char *nm_strerror_native (int errsv);
-
-/*****************************************************************************/
-
-#endif /* __NM_ERRNO_H__ */
diff --git a/shared/nm-utils/nm-glib.h b/shared/nm-utils/nm-glib.h
deleted file mode 100644
index e941e067..00000000
--- a/shared/nm-utils/nm-glib.h
+++ /dev/null
@@ -1,567 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Copyright 2008 - 2018 Red Hat, Inc.
- */
-
-#ifndef __NM_GLIB_H__
-#define __NM_GLIB_H__
-
-/*****************************************************************************/
-
-#ifndef __NM_MACROS_INTERNAL_H__
-#error "nm-glib.h requires nm-macros-internal.h. Do not include this directly"
-#endif
-
-/*****************************************************************************/
-
-#ifdef __clang__
-
-#undef G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-#undef G_GNUC_END_IGNORE_DEPRECATIONS
-
-#define G_GNUC_BEGIN_IGNORE_DEPRECATIONS \
-    _Pragma("clang diagnostic push") \
-    _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
-
-#define G_GNUC_END_IGNORE_DEPRECATIONS \
-    _Pragma("clang diagnostic pop")
-
-#endif
-
-/*****************************************************************************/
-
-static inline void
-__g_type_ensure (GType type)
-{
-#if !GLIB_CHECK_VERSION(2,34,0)
-	if (G_UNLIKELY (type == (GType)-1))
-		g_error ("can't happen");
-#else
-	G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
-	g_type_ensure (type);
-	G_GNUC_END_IGNORE_DEPRECATIONS;
-#endif
-}
-#define g_type_ensure __g_type_ensure
-
-/*****************************************************************************/
-
-#if !GLIB_CHECK_VERSION(2,34,0)
-
-#define g_clear_pointer(pp, destroy) \
-    G_STMT_START {                                                                 \
-        G_STATIC_ASSERT (sizeof *(pp) == sizeof (gpointer));                       \
-        /* Only one access, please */                                              \
-        gpointer *_pp = (gpointer *) (pp);                                         \
-        gpointer _p;                                                               \
-        /* This assignment is needed to avoid a gcc warning */                     \
-        GDestroyNotify _destroy = (GDestroyNotify) (destroy);                      \
-                                                                                   \
-        _p = *_pp;                                                                 \
-        if (_p)                                                                    \
-        {                                                                          \
-            *_pp = NULL;                                                           \
-            _destroy (_p);                                                         \
-        }                                                                          \
-    } G_STMT_END
-
-#endif
-
-/*****************************************************************************/
-
-#if !GLIB_CHECK_VERSION(2,34,0)
-
-/* These are used to clean up the output of test programs; we can just let
- * them no-op in older glib.
- */
-#define g_test_expect_message(log_domain, log_level, pattern)
-#define g_test_assert_expected_messages()
-
-#else
-
-/* We build with -DGLIB_MAX_ALLOWED_VERSION set to 2.32 to make sure we don't
- * accidentally use new API that we shouldn't. But we don't want warnings for
- * the APIs that we emulate above.
- */
-
-#define g_test_expect_message(domain, level, format...) \
-	G_STMT_START { \
-		G_GNUC_BEGIN_IGNORE_DEPRECATIONS \
-		g_test_expect_message (domain, level, format); \
-		G_GNUC_END_IGNORE_DEPRECATIONS \
-	} G_STMT_END
-
-#define g_test_assert_expected_messages_internal(domain, file, line, func) \
-	G_STMT_START { \
-		G_GNUC_BEGIN_IGNORE_DEPRECATIONS \
-		g_test_assert_expected_messages_internal (domain, file, line, func); \
-		G_GNUC_END_IGNORE_DEPRECATIONS \
-	} G_STMT_END
-
-#endif
-
-/*****************************************************************************/
-
-#if GLIB_CHECK_VERSION (2, 35, 0)
-/* For glib >= 2.36, g_type_init() is deprecated.
- * But since 2.35.1 (7c42ab23b55c43ab96d0ac2124b550bf1f49c1ec) this function
- * does nothing. Replace the call with empty statement. */
-#define nm_g_type_init()     G_STMT_START { (void) 0; } G_STMT_END
-#else
-#define nm_g_type_init()     G_STMT_START { g_type_init (); } G_STMT_END
-#endif
-
-/*****************************************************************************/
-
-/* g_test_initialized() is only available since glib 2.36. */
-#if !GLIB_CHECK_VERSION (2, 36, 0)
-#define g_test_initialized() (g_test_config_vars->test_initialized)
-#endif
-
-/*****************************************************************************/
-
-/* g_assert_cmpmem() is only available since glib 2.46. */
-#if !GLIB_CHECK_VERSION (2, 45, 7)
-#define g_assert_cmpmem(m1, l1, m2, l2) G_STMT_START {\
-                                             gconstpointer __m1 = m1, __m2 = m2; \
-                                             int __l1 = l1, __l2 = l2; \
-                                             if (__l1 != __l2) \
-                                               g_assertion_message_cmpnum (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
-                                                                           #l1 " (len(" #m1 ")) == " #l2 " (len(" #m2 "))", __l1, "==", __l2, 'i'); \
-                                             else if (memcmp (__m1, __m2, __l1) != 0) \
-                                               g_assertion_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
-                                                                    "assertion failed (" #m1 " == " #m2 ")"); \
-                                        } G_STMT_END
-#endif
-
-/*****************************************************************************/
-
-/* Rumtime check for glib version. First do a compile time check which
- * (if satisfied) shortcuts the runtime check. */
-static inline gboolean
-nm_glib_check_version (guint major, guint minor, guint micro)
-{
-	return    GLIB_CHECK_VERSION (major, minor, micro)
-	       || (   (   glib_major_version > major)
-	           || (   glib_major_version == major
-	               && glib_minor_version > minor)
-	           || (   glib_major_version == major
-	               && glib_minor_version == minor
-	               && glib_micro_version < micro));
-}
-
-/*****************************************************************************/
-
-/* g_test_skip() is only available since glib 2.38. Add a compatibility wrapper. */
-static inline void
-__nmtst_g_test_skip (const char *msg)
-{
-#if GLIB_CHECK_VERSION (2, 38, 0)
-	G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-	g_test_skip (msg);
-	G_GNUC_END_IGNORE_DEPRECATIONS
-#else
-	g_debug ("%s", msg);
-#endif
-}
-#define g_test_skip __nmtst_g_test_skip
-
-/*****************************************************************************/
-
-/* g_test_add_data_func_full() is only available since glib 2.34. Add a compatibility wrapper. */
-static inline void
-__g_test_add_data_func_full (const char     *testpath,
-                             gpointer        test_data,
-                             GTestDataFunc   test_func,
-                             GDestroyNotify  data_free_func)
-{
-#if GLIB_CHECK_VERSION (2, 34, 0)
-	G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-	g_test_add_data_func_full (testpath, test_data, test_func, data_free_func);
-	G_GNUC_END_IGNORE_DEPRECATIONS
-#else
-	g_return_if_fail (testpath != NULL);
-	g_return_if_fail (testpath[0] == '/');
-	g_return_if_fail (test_func != NULL);
-
-	g_test_add_vtable (testpath, 0, test_data, NULL,
-	                   (GTestFixtureFunc) test_func,
-	                   (GTestFixtureFunc) data_free_func);
-#endif
-}
-#define g_test_add_data_func_full __g_test_add_data_func_full
-
-/*****************************************************************************/
-
-#if !GLIB_CHECK_VERSION (2, 34, 0)
-#define G_DEFINE_QUARK(QN, q_n)               \
-GQuark                                        \
-q_n##_quark (void)                            \
-{                                             \
-	static GQuark q;                          \
-                                              \
-	if G_UNLIKELY (q == 0)                    \
-		q = g_quark_from_static_string (#QN); \
-                                              \
-	return q;                                 \
-}
-#endif
-
-/*****************************************************************************/
-
-static inline gboolean
-nm_g_hash_table_replace (GHashTable *hash, gpointer key, gpointer value)
-{
-	/* glib 2.40 added a return value indicating whether the key already existed
-	 * (910191597a6c2e5d5d460e9ce9efb4f47d9cc63c). */
-#if GLIB_CHECK_VERSION(2, 40, 0)
-	return g_hash_table_replace (hash, key, value);
-#else
-	gboolean contained = g_hash_table_contains (hash, key);
-
-	g_hash_table_replace (hash, key, value);
-	return !contained;
-#endif
-}
-
-static inline gboolean
-nm_g_hash_table_insert (GHashTable *hash, gpointer key, gpointer value)
-{
-	/* glib 2.40 added a return value indicating whether the key already existed
-	 * (910191597a6c2e5d5d460e9ce9efb4f47d9cc63c). */
-#if GLIB_CHECK_VERSION(2, 40, 0)
-	return g_hash_table_insert (hash, key, value);
-#else
-	gboolean contained = g_hash_table_contains (hash, key);
-
-	g_hash_table_insert (hash, key, value);
-	return !contained;
-#endif
-}
-
-static inline gboolean
-nm_g_hash_table_add (GHashTable *hash, gpointer key)
-{
-	/* glib 2.40 added a return value indicating whether the key already existed
-	 * (910191597a6c2e5d5d460e9ce9efb4f47d9cc63c). */
-#if GLIB_CHECK_VERSION(2, 40, 0)
-	return g_hash_table_add (hash, key);
-#else
-	gboolean contained = g_hash_table_contains (hash, key);
-
-	g_hash_table_add (hash, key);
-	return !contained;
-#endif
-}
-
-/*****************************************************************************/
-
-#if !GLIB_CHECK_VERSION(2, 40, 0) || defined (NM_GLIB_COMPAT_H_TEST)
-static inline void
-_nm_g_ptr_array_insert (GPtrArray *array,
-                        int        index_,
-                        gpointer   data)
-{
-	g_return_if_fail (array);
-	g_return_if_fail (index_ >= -1);
-	g_return_if_fail (index_ <= (int) array->len);
-
-	g_ptr_array_add (array, data);
-
-	if (index_ != -1 && index_ != (int) (array->len - 1)) {
-		memmove (&(array->pdata[index_ + 1]),
-		         &(array->pdata[index_]),
-		         (array->len - index_ - 1) * sizeof (gpointer));
-		array->pdata[index_] = data;
-	}
-}
-#endif
-
-#if !GLIB_CHECK_VERSION(2, 40, 0)
-#define g_ptr_array_insert(array, index, data) G_STMT_START { _nm_g_ptr_array_insert (array, index, data); } G_STMT_END
-#else
-#define g_ptr_array_insert(array, index, data) \
-	G_STMT_START { \
-		G_GNUC_BEGIN_IGNORE_DEPRECATIONS \
-		g_ptr_array_insert (array, index, data); \
-		G_GNUC_END_IGNORE_DEPRECATIONS \
-	} G_STMT_END
-#endif
-
-/*****************************************************************************/
-
-#if !GLIB_CHECK_VERSION (2, 40, 0)
-static inline gboolean
-_g_key_file_save_to_file (GKeyFile     *key_file,
-                          const char   *filename,
-                          GError      **error)
-{
-	char *contents;
-	gboolean success;
-	gsize length;
-
-	g_return_val_if_fail (key_file != NULL, FALSE);
-	g_return_val_if_fail (filename != NULL, FALSE);
-	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-	contents = g_key_file_to_data (key_file, &length, NULL);
-	g_assert (contents != NULL);
-
-	success = g_file_set_contents (filename, contents, length, error);
-	g_free (contents);
-
-	return success;
-}
-#define g_key_file_save_to_file(key_file, filename, error) \
-	_g_key_file_save_to_file (key_file, filename, error)
-#else
-#define g_key_file_save_to_file(key_file, filename, error) \
-	({ \
-		gboolean _success; \
-		\
-		G_GNUC_BEGIN_IGNORE_DEPRECATIONS \
-		_success = g_key_file_save_to_file (key_file, filename, error); \
-		G_GNUC_END_IGNORE_DEPRECATIONS \
-		_success; \
-	})
-#endif
-
-/*****************************************************************************/
-
-#if GLIB_CHECK_VERSION (2, 36, 0)
-#define g_credentials_get_unix_pid(creds, error) \
-	({ \
-		G_GNUC_BEGIN_IGNORE_DEPRECATIONS \
-			(g_credentials_get_unix_pid) ((creds), (error)); \
-		G_GNUC_END_IGNORE_DEPRECATIONS \
-	})
-#else
-#define g_credentials_get_unix_pid(creds, error) \
-	({ \
-		struct ucred *native_creds; \
-		 \
-		native_creds = g_credentials_get_native ((creds), G_CREDENTIALS_TYPE_LINUX_UCRED); \
-		g_assert (native_creds); \
-		native_creds->pid; \
-	})
-#endif
-
-/*****************************************************************************/
-
-#if !GLIB_CHECK_VERSION(2, 40, 0) || defined (NM_GLIB_COMPAT_H_TEST)
-static inline gpointer *
-_nm_g_hash_table_get_keys_as_array (GHashTable *hash_table,
-                                    guint      *length)
-{
-	GHashTableIter iter;
-	gpointer key, *ret;
-	guint i = 0;
-
-	g_return_val_if_fail (hash_table, NULL);
-
-	ret = g_new0 (gpointer, g_hash_table_size (hash_table) + 1);
-	g_hash_table_iter_init (&iter, hash_table);
-
-	while (g_hash_table_iter_next (&iter, &key, NULL))
-		ret[i++] = key;
-
-	ret[i] = NULL;
-
-	if (length)
-		*length = i;
-
-	return ret;
-}
-#endif
-#if !GLIB_CHECK_VERSION(2, 40, 0)
-#define g_hash_table_get_keys_as_array(hash_table, length) \
-	({ \
-		_nm_g_hash_table_get_keys_as_array (hash_table, length); \
-	})
-#else
-#define g_hash_table_get_keys_as_array(hash_table, length) \
-	({ \
-		G_GNUC_BEGIN_IGNORE_DEPRECATIONS \
-			(g_hash_table_get_keys_as_array) ((hash_table), (length)); \
-		G_GNUC_END_IGNORE_DEPRECATIONS \
-	})
-#endif
-
-/*****************************************************************************/
-
-#ifndef g_info
-/* g_info was only added with 2.39.2 */
-#define g_info(...)     g_log (G_LOG_DOMAIN,         \
-                               G_LOG_LEVEL_INFO,     \
-                               __VA_ARGS__)
-#endif
-
-/*****************************************************************************/
-
-#if !GLIB_CHECK_VERSION(2, 44, 0)
-static inline gpointer
-g_steal_pointer (gpointer pp)
-{
-	gpointer *ptr = (gpointer *) pp;
-	gpointer ref;
-
-	ref = *ptr;
-	*ptr = NULL;
-
-	return ref;
-}
-#endif
-
-#ifdef g_steal_pointer
-#undef g_steal_pointer
-#endif
-#define g_steal_pointer(pp) \
-	((typeof (*(pp))) g_steal_pointer (pp))
-
-/*****************************************************************************/
-
-static inline gboolean
-_nm_g_strv_contains (const char * const *strv,
-                     const char          *str)
-{
-#if !GLIB_CHECK_VERSION(2, 44, 0)
-	g_return_val_if_fail (strv != NULL, FALSE);
-	g_return_val_if_fail (str != NULL, FALSE);
-
-	for (; *strv != NULL; strv++) {
-		if (g_str_equal (str, *strv))
-			return TRUE;
-	}
-
-	return FALSE;
-#else
-	G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-	return g_strv_contains (strv, str);
-	G_GNUC_END_IGNORE_DEPRECATIONS
-#endif
-}
-#define g_strv_contains _nm_g_strv_contains
-
-/*****************************************************************************/
-
-static inline GVariant *
-_nm_g_variant_new_take_string (char *string)
-{
-#if !GLIB_CHECK_VERSION(2, 36, 0)
-	GVariant *value;
-
-	g_return_val_if_fail (string != NULL, NULL);
-	g_return_val_if_fail (g_utf8_validate (string, -1, NULL), NULL);
-
-	value = g_variant_new_string (string);
-	g_free (string);
-	return value;
-#elif !GLIB_CHECK_VERSION(2, 38, 0)
-	GVariant *value;
-	GBytes *bytes;
-
-	g_return_val_if_fail (string != NULL, NULL);
-	g_return_val_if_fail (g_utf8_validate (string, -1, NULL), NULL);
-
-	bytes = g_bytes_new_take (string, strlen (string) + 1);
-	value = g_variant_new_from_bytes (G_VARIANT_TYPE_STRING, bytes, TRUE);
-	g_bytes_unref (bytes);
-
-	return value;
-#else
-	G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-	return g_variant_new_take_string (string);
-	G_GNUC_END_IGNORE_DEPRECATIONS
-#endif
-}
-#define g_variant_new_take_string _nm_g_variant_new_take_string
-
-/*****************************************************************************/
-
-#if !GLIB_CHECK_VERSION(2, 38, 0)
-_nm_printf (1, 2)
-static inline GVariant *
-_nm_g_variant_new_printf (const char *format_string, ...)
-{
-	char *string;
-	va_list ap;
-
-	g_return_val_if_fail (format_string, NULL);
-
-	va_start (ap, format_string);
-	string = g_strdup_vprintf (format_string, ap);
-	va_end (ap);
-
-	return g_variant_new_take_string (string);
-}
-#define g_variant_new_printf(...) _nm_g_variant_new_printf(__VA_ARGS__)
-#else
-#define g_variant_new_printf(...) \
-	({ \
-		GVariant *_v; \
-		\
-		G_GNUC_BEGIN_IGNORE_DEPRECATIONS \
-		_v = g_variant_new_printf (__VA_ARGS__); \
-		G_GNUC_END_IGNORE_DEPRECATIONS \
-		_v; \
-	})
-#endif
-
-/*****************************************************************************/
-
-#if !GLIB_CHECK_VERSION (2, 56, 0)
-#define g_object_ref(Obj)      ((typeof(Obj)) g_object_ref (Obj))
-#define g_object_ref_sink(Obj) ((typeof(Obj)) g_object_ref_sink (Obj))
-#endif
-
-/*****************************************************************************/
-
-#ifndef g_autofree
-/* we still don't rely on recent glib to provide g_autofree. Hence, we continue
- * to use our gs_* free macros that we took from libgsystem.
- *
- * To ease migration towards g_auto*, add a compat define for g_autofree. */
-#define g_autofree gs_free
-#endif
-
-/*****************************************************************************/
-
-#if !GLIB_CHECK_VERSION (2, 47, 1)
-/* Older versions of g_value_unset() only allowed to unset a GValue which
- * was initialized previously. This was relaxed ([1], [2], [3]).
- *
- * Our nm_auto_unset_gvalue macro requires to be able to call g_value_unset().
- * Also, it is our general practice to allow for that. Add a compat implementation.
- *
- * [1] https://gitlab.gnome.org/GNOME/glib/commit/4b2d92a864f1505f1b08eb639d74293fa32681da
- * [2] commit "Allow passing unset GValues to g_value_unset()"
- * [3] https://bugzilla.gnome.org/show_bug.cgi?id=755766
- */
-static inline void
-_nm_g_value_unset (GValue *value)
-{
-	g_return_if_fail (value);
-
-	if (value->g_type != 0)
-		g_value_unset (value);
-}
-#define g_value_unset _nm_g_value_unset
-#endif
-
-/*****************************************************************************/
-
-#endif  /* __NM_GLIB_H__ */
diff --git a/shared/nm-utils/nm-hash-utils.c b/shared/nm-utils/nm-hash-utils.c
deleted file mode 100644
index 6e728e6b..00000000
--- a/shared/nm-utils/nm-hash-utils.c
+++ /dev/null
@@ -1,196 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-/* NetworkManager -- Network link manager
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA.
- *
- * (C) Copyright 2017 Red Hat, Inc.
- */
-
-#include "nm-default.h"
-
-#include "nm-hash-utils.h"
-
-#include <stdint.h>
-
-#include "nm-shared-utils.h"
-#include "nm-random-utils.h"
-
-/*****************************************************************************/
-
-#define HASH_KEY_SIZE 16u
-#define HASH_KEY_SIZE_GUINT ((HASH_KEY_SIZE + sizeof (guint) - 1) / sizeof (guint))
-
-G_STATIC_ASSERT (sizeof (guint) * HASH_KEY_SIZE_GUINT >= HASH_KEY_SIZE);
-
-static const guint8 *volatile global_seed = NULL;
-
-static const guint8 *
-_get_hash_key_init (void)
-{
-	static gsize g_lock;
-	/* the returned hash is aligned to guin64, hence, it is safe
-	 * to use it as guint* or guint64* pointer. */
-	static union {
-		guint8 v8[HASH_KEY_SIZE];
-	} g_arr _nm_alignas (guint64);
-	const guint8 *g;
-	union {
-		guint8 v8[HASH_KEY_SIZE];
-		guint vuint;
-	} t_arr;
-
-again:
-	g = g_atomic_pointer_get (&global_seed);
-	if (G_LIKELY (g != NULL)) {
-		nm_assert (g == g_arr.v8);
-		return g;
-	}
-
-	{
-		CSipHash siph_state;
-		uint64_t h;
-
-		/* initialize a random key in t_arr. */
-
-		nm_utils_random_bytes (&t_arr, sizeof (t_arr));
-
-		/* use siphash() of the key-size, to mangle the first guint. Otherwise,
-		 * the first guint has only the entropy that nm_utils_random_bytes()
-		 * generated for the first 4 bytes and relies on a good random generator.
-		 *
-		 * The first int is especially interesting for nm_hash_static() below, and we
-		 * want to have it all the entropy of t_arr. */
-		c_siphash_init (&siph_state, t_arr.v8);
-		c_siphash_append (&siph_state, (const guint8 *) &t_arr, sizeof (t_arr));
-		h = c_siphash_finalize (&siph_state);
-		if (sizeof (guint) < sizeof (h))
-			t_arr.vuint = t_arr.vuint ^ ((guint) (h & 0xFFFFFFFFu)) ^ ((guint) (h >> 32));
-		else
-			t_arr.vuint = t_arr.vuint ^ ((guint) (h & 0xFFFFFFFFu));
-	}
-
-	if (!g_once_init_enter (&g_lock)) {
-		/* lost a race. The random key is already initialized. */
-		goto again;
-	}
-
-	memcpy (g_arr.v8, t_arr.v8, HASH_KEY_SIZE);
-	g = g_arr.v8;
-	g_atomic_pointer_set (&global_seed, g);
-	g_once_init_leave (&g_lock, 1);
-	return g;
-}
-
-#define _get_hash_key() \
-	({ \
-		const guint8 *_g; \
-		\
-		_g = g_atomic_pointer_get (&global_seed); \
-		if (G_UNLIKELY (!_g)) \
-			_g = _get_hash_key_init (); \
-		_g; \
-	})
-
-guint
-nm_hash_static (guint static_seed)
-{
-	/* note that we only xor the static_seed with the key.
-	 * We don't use siphash, which would mix the bits better.
-	 * Note that this doesn't matter, because static_seed is not
-	 * supposed to be a value that you are hashing (for that, use
-	 * full siphash).
-	 * Instead, different callers may set a different static_seed
-	 * so that nm_hash_str(NULL) != nm_hash_ptr(NULL).
-	 *
-	 * Also, ensure that we don't return zero.
-	 */
-	return ((*((const guint *) _get_hash_key ())) ^ static_seed)
-	       ?: static_seed ?: 3679500967u;
-}
-
-void
-nm_hash_siphash42_init (CSipHash *h, guint static_seed)
-{
-	const guint8 *g;
-	guint seed[HASH_KEY_SIZE_GUINT];
-
-	nm_assert (h);
-
-	g = _get_hash_key ();
-	memcpy (seed, g, HASH_KEY_SIZE);
-	seed[0] ^= static_seed;
-	c_siphash_init (h, (const guint8 *) seed);
-}
-
-guint
-nm_hash_str (const char *str)
-{
-	NMHashState h;
-
-	if (!str)
-		return nm_hash_static (1867854211u);
-	nm_hash_init (&h, 1867854211u);
-	nm_hash_update_str (&h, str);
-	return nm_hash_complete (&h);
-}
-
-guint
-nm_str_hash (gconstpointer str)
-{
-	return nm_hash_str (str);
-}
-
-guint
-nm_hash_ptr (gconstpointer ptr)
-{
-	NMHashState h;
-
-	if (!ptr)
-		return nm_hash_static (2907677551u);
-	nm_hash_init (&h, 2907677551u);
-	nm_hash_update (&h, &ptr, sizeof (ptr));
-	return nm_hash_complete (&h);
-}
-
-guint
-nm_direct_hash (gconstpointer ptr)
-{
-	return nm_hash_ptr (ptr);
-}
-
-/*****************************************************************************/
-
-guint
-nm_pstr_hash (gconstpointer p)
-{
-	const char *const*s = p;
-
-	if (!s)
-		return nm_hash_static (101061439u);
-	return nm_hash_str (*s);
-}
-
-gboolean
-nm_pstr_equal (gconstpointer a, gconstpointer b)
-{
-	const char *const*s1 = a;
-	const char *const*s2 = b;
-
-	return    (s1 == s2)
-	       || (   s1
-	           && s2
-	           && nm_streq0 (*s1, *s2));
-}
diff --git a/shared/nm-utils/nm-hash-utils.h b/shared/nm-utils/nm-hash-utils.h
deleted file mode 100644
index 1a1e44f5..00000000
--- a/shared/nm-utils/nm-hash-utils.h
+++ /dev/null
@@ -1,290 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-/* NetworkManager -- Network link manager
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA.
- *
- * (C) Copyright 2017 Red Hat, Inc.
- */
-
-#ifndef __NM_HASH_UTILS_H__
-#define __NM_HASH_UTILS_H__
-
-#include "c-siphash/src/c-siphash.h"
-#include "nm-macros-internal.h"
-
-/*****************************************************************************/
-
-void nm_hash_siphash42_init (CSipHash *h, guint static_seed);
-
-/* Siphash24 of binary buffer @arr and @len, using the randomized seed from
- * other NMHash functions.
- *
- * Note, that this is guaranteed to use siphash42 under the hood (contrary to
- * all other NMHash API, which leave this undefined). That matters at the point,
- * where the caller needs to be sure that a reasonably strong hasing algorithm
- * is used.  (Yes, NMHash is all about siphash24, but otherwise that is not promised
- * anywhere).
- *
- * Another difference is, that this returns guint64 (not guint like other NMHash functions).
- *
- * Another difference is, that this may also return zero (not like nm_hash_complete()).
- *
- * Then, why not use c_siphash_hash() directly? Because this also uses the randomized,
- * per-run hash-seed like nm_hash_init(). So, you get siphash24 with a random
- * seed (which is cached for the current run of the program).
- */
-static inline guint64
-nm_hash_siphash42 (guint static_seed, const void *ptr, gsize n)
-{
-	CSipHash h;
-
-	nm_hash_siphash42_init (&h, static_seed);
-	c_siphash_append (&h, ptr, n);
-	return c_siphash_finalize (&h);
-}
-
-/*****************************************************************************/
-
-struct _NMHashState {
-	CSipHash _state;
-};
-
-typedef struct _NMHashState NMHashState;
-
-guint nm_hash_static (guint static_seed);
-
-static inline void
-nm_hash_init (NMHashState *state, guint static_seed)
-{
-	nm_assert (state);
-
-	nm_hash_siphash42_init (&state->_state, static_seed);
-}
-
-static inline guint64
-nm_hash_complete_u64 (NMHashState *state)
-{
-	nm_assert (state);
-
-	/* this returns the native u64 hash value. Note that this differs
-	 * from nm_hash_complete() in two ways:
-	 *
-	 * - the type, guint64 vs. guint.
-	 * - nm_hash_complete() never returns zero. */
-	return c_siphash_finalize (&state->_state);
-}
-
-static inline guint
-nm_hash_complete (NMHashState *state)
-{
-	guint64 h;
-
-	h = nm_hash_complete_u64 (state);
-
-	/* we don't ever want to return a zero hash.
-	 *
-	 * NMPObject requires that in _idx_obj_part(), and it's just a good idea. */
-	return (((guint) (h >> 32)) ^ ((guint) h)) ?: 1396707757u;
-}
-
-static inline void
-nm_hash_update (NMHashState *state, const void *ptr, gsize n)
-{
-	nm_assert (state);
-	nm_assert (ptr);
-	nm_assert (n > 0);
-
-	/* Note: the data passed in here might be sensitive data (secrets),
-	 * that we should nm_explicty_zero() afterwards. However, since
-	 * we are using siphash24 with a random key, that is not really
-	 * necessary. Something to keep in mind, if we ever move away from
-	 * this hash implementation. */
-	c_siphash_append (&state->_state, ptr, n);
-}
-
-#define nm_hash_update_val(state, val) \
-	G_STMT_START { \
-		typeof (val) _val = (val); \
-		\
-		nm_hash_update ((state), &_val, sizeof (_val)); \
-	} G_STMT_END
-
-#define nm_hash_update_valp(state, val) \
-	nm_hash_update ((state), (val), sizeof (*(val))) \
-
-static inline void
-nm_hash_update_bool (NMHashState *state, bool val)
-{
-	nm_hash_update (state, &val, sizeof (val));
-}
-
-#define _NM_HASH_COMBINE_BOOLS_x_1( t, y)      ((y) ? ((t) (1ull <<  0)) : ((t) 0ull))
-#define _NM_HASH_COMBINE_BOOLS_x_2( t, y, ...) ((y) ? ((t) (1ull <<  1)) : ((t) 0ull)) | _NM_HASH_COMBINE_BOOLS_x_1  (t, __VA_ARGS__)
-#define _NM_HASH_COMBINE_BOOLS_x_3( t, y, ...) ((y) ? ((t) (1ull <<  2)) : ((t) 0ull)) | _NM_HASH_COMBINE_BOOLS_x_2  (t, __VA_ARGS__)
-#define _NM_HASH_COMBINE_BOOLS_x_4( t, y, ...) ((y) ? ((t) (1ull <<  3)) : ((t) 0ull)) | _NM_HASH_COMBINE_BOOLS_x_3  (t, __VA_ARGS__)
-#define _NM_HASH_COMBINE_BOOLS_x_5( t, y, ...) ((y) ? ((t) (1ull <<  4)) : ((t) 0ull)) | _NM_HASH_COMBINE_BOOLS_x_4  (t, __VA_ARGS__)
-#define _NM_HASH_COMBINE_BOOLS_x_6( t, y, ...) ((y) ? ((t) (1ull <<  5)) : ((t) 0ull)) | _NM_HASH_COMBINE_BOOLS_x_5  (t, __VA_ARGS__)
-#define _NM_HASH_COMBINE_BOOLS_x_7( t, y, ...) ((y) ? ((t) (1ull <<  6)) : ((t) 0ull)) | _NM_HASH_COMBINE_BOOLS_x_6  (t, __VA_ARGS__)
-#define _NM_HASH_COMBINE_BOOLS_x_8( t, y, ...) ((y) ? ((t) (1ull <<  7)) : ((t) 0ull)) | _NM_HASH_COMBINE_BOOLS_x_7  (t, __VA_ARGS__)
-#define _NM_HASH_COMBINE_BOOLS_x_9( t, y, ...) ((y) ? ((t) (1ull <<  8)) : ((t) 0ull)) | (G_STATIC_ASSERT_EXPR (sizeof (t) >= 2), (_NM_HASH_COMBINE_BOOLS_x_8  (t, __VA_ARGS__)))
-#define _NM_HASH_COMBINE_BOOLS_x_10(t, y, ...) ((y) ? ((t) (1ull <<  9)) : ((t) 0ull)) | _NM_HASH_COMBINE_BOOLS_x_9  (t, __VA_ARGS__)
-#define _NM_HASH_COMBINE_BOOLS_x_11(t, y, ...) ((y) ? ((t) (1ull << 10)) : ((t) 0ull)) | _NM_HASH_COMBINE_BOOLS_x_10 (t, __VA_ARGS__)
-#define _NM_HASH_COMBINE_BOOLS_n2(t, n, ...) _NM_HASH_COMBINE_BOOLS_x_##n (t, __VA_ARGS__)
-#define _NM_HASH_COMBINE_BOOLS_n(t, n, ...) _NM_HASH_COMBINE_BOOLS_n2(t, n, __VA_ARGS__)
-
-#define NM_HASH_COMBINE_BOOLS(type, ...) ((type) (_NM_HASH_COMBINE_BOOLS_n(type, NM_NARG (__VA_ARGS__), __VA_ARGS__)))
-
-#define nm_hash_update_bools(state, ...) \
-	nm_hash_update_val (state, NM_HASH_COMBINE_BOOLS (guint8, __VA_ARGS__))
-
-#define _NM_HASH_COMBINE_VALS_typ_x_1( y)       typeof (y) _v1;
-#define _NM_HASH_COMBINE_VALS_typ_x_2( y, ...)  typeof (y) _v2;  _NM_HASH_COMBINE_VALS_typ_x_1  (__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_typ_x_3( y, ...)  typeof (y) _v3;  _NM_HASH_COMBINE_VALS_typ_x_2  (__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_typ_x_4( y, ...)  typeof (y) _v4;  _NM_HASH_COMBINE_VALS_typ_x_3  (__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_typ_x_5( y, ...)  typeof (y) _v5;  _NM_HASH_COMBINE_VALS_typ_x_4  (__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_typ_x_6( y, ...)  typeof (y) _v6;  _NM_HASH_COMBINE_VALS_typ_x_5  (__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_typ_x_7( y, ...)  typeof (y) _v7;  _NM_HASH_COMBINE_VALS_typ_x_6  (__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_typ_x_8( y, ...)  typeof (y) _v8;  _NM_HASH_COMBINE_VALS_typ_x_7  (__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_typ_x_9( y, ...)  typeof (y) _v9;  _NM_HASH_COMBINE_VALS_typ_x_8  (__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_typ_x_10(y, ...)  typeof (y) _v10; _NM_HASH_COMBINE_VALS_typ_x_9  (__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_typ_x_11(y, ...)  typeof (y) _v11; _NM_HASH_COMBINE_VALS_typ_x_10  (__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_typ_x_12(y, ...)  typeof (y) _v12; _NM_HASH_COMBINE_VALS_typ_x_11 (__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_typ_x_13(y, ...)  typeof (y) _v13; _NM_HASH_COMBINE_VALS_typ_x_12 (__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_typ_x_14(y, ...)  typeof (y) _v14; _NM_HASH_COMBINE_VALS_typ_x_13 (__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_typ_x_15(y, ...)  typeof (y) _v15; _NM_HASH_COMBINE_VALS_typ_x_14 (__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_typ_x_16(y, ...)  typeof (y) _v16; _NM_HASH_COMBINE_VALS_typ_x_15 (__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_typ_x_17(y, ...)  typeof (y) _v17; _NM_HASH_COMBINE_VALS_typ_x_16 (__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_typ_x_18(y, ...)  typeof (y) _v18; _NM_HASH_COMBINE_VALS_typ_x_17 (__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_typ_x_19(y, ...)  typeof (y) _v19; _NM_HASH_COMBINE_VALS_typ_x_18 (__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_typ_x_20(y, ...)  typeof (y) _v20; _NM_HASH_COMBINE_VALS_typ_x_19 (__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_typ_n2(n, ...) _NM_HASH_COMBINE_VALS_typ_x_##n (__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_typ_n(n, ...) _NM_HASH_COMBINE_VALS_typ_n2(n, __VA_ARGS__)
-
-#define _NM_HASH_COMBINE_VALS_val_x_1( y)       ._v1  = (y),
-#define _NM_HASH_COMBINE_VALS_val_x_2( y, ...)  ._v2  = (y), _NM_HASH_COMBINE_VALS_val_x_1  (__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_val_x_3( y, ...)  ._v3  = (y), _NM_HASH_COMBINE_VALS_val_x_2  (__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_val_x_4( y, ...)  ._v4  = (y), _NM_HASH_COMBINE_VALS_val_x_3  (__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_val_x_5( y, ...)  ._v5  = (y), _NM_HASH_COMBINE_VALS_val_x_4  (__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_val_x_6( y, ...)  ._v6  = (y), _NM_HASH_COMBINE_VALS_val_x_5  (__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_val_x_7( y, ...)  ._v7  = (y), _NM_HASH_COMBINE_VALS_val_x_6  (__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_val_x_8( y, ...)  ._v8  = (y), _NM_HASH_COMBINE_VALS_val_x_7  (__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_val_x_9( y, ...)  ._v9  = (y), _NM_HASH_COMBINE_VALS_val_x_8  (__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_val_x_10(y, ...)  ._v10 = (y), _NM_HASH_COMBINE_VALS_val_x_9  (__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_val_x_11(y, ...)  ._v11 = (y), _NM_HASH_COMBINE_VALS_val_x_10  (__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_val_x_12(y, ...)  ._v12 = (y), _NM_HASH_COMBINE_VALS_val_x_11 (__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_val_x_13(y, ...)  ._v13 = (y), _NM_HASH_COMBINE_VALS_val_x_12 (__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_val_x_14(y, ...)  ._v14 = (y), _NM_HASH_COMBINE_VALS_val_x_13 (__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_val_x_15(y, ...)  ._v15 = (y), _NM_HASH_COMBINE_VALS_val_x_14 (__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_val_x_16(y, ...)  ._v16 = (y), _NM_HASH_COMBINE_VALS_val_x_15 (__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_val_x_17(y, ...)  ._v17 = (y), _NM_HASH_COMBINE_VALS_val_x_16 (__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_val_x_18(y, ...)  ._v18 = (y), _NM_HASH_COMBINE_VALS_val_x_17 (__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_val_x_19(y, ...)  ._v19 = (y), _NM_HASH_COMBINE_VALS_val_x_18 (__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_val_x_20(y, ...)  ._v20 = (y), _NM_HASH_COMBINE_VALS_val_x_19 (__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_val_n2(n, ...) _NM_HASH_COMBINE_VALS_val_x_##n (__VA_ARGS__)
-#define _NM_HASH_COMBINE_VALS_val_n(n, ...) _NM_HASH_COMBINE_VALS_val_n2(n, __VA_ARGS__)
-
-/* NM_HASH_COMBINE_VALS() is faster then nm_hash_update_val() as it combines multiple
- * calls to nm_hash_update() using a packed structure. */
-#define NM_HASH_COMBINE_VALS(var, ...) \
-	const struct _nm_packed { \
-		_NM_HASH_COMBINE_VALS_typ_n (NM_NARG (__VA_ARGS__), __VA_ARGS__) \
-	} var _nm_alignas (guint64) = { \
-		_NM_HASH_COMBINE_VALS_val_n (NM_NARG (__VA_ARGS__), __VA_ARGS__) \
-	}
-
-/* nm_hash_update_vals() is faster then nm_hash_update_val() as it combines multiple
- * calls to nm_hash_update() using a packed structure. */
-#define nm_hash_update_vals(state, ...) \
-	G_STMT_START { \
-		NM_HASH_COMBINE_VALS (_val, __VA_ARGS__); \
-		\
-		nm_hash_update ((state), &_val, sizeof (_val)); \
-	} G_STMT_END
-
-static inline void
-nm_hash_update_mem (NMHashState *state, const void *ptr, gsize n)
-{
-	/* This also hashes the length of the data. That means,
-	 * hashing two consecutive binary fields (of arbitrary
-	 * length), will hash differently. That is,
-	 * [[1,1], []] differs from [[1],[1]].
-	 *
-	 * If you have a constant length (sizeof), use nm_hash_update()
-	 * instead. */
-	nm_hash_update (state, &n, sizeof (n));
-	if (n > 0)
-		nm_hash_update (state, ptr, n);
-}
-
-static inline void
-nm_hash_update_str0 (NMHashState *state, const char *str)
-{
-	if (str)
-		nm_hash_update_mem (state, str, strlen (str));
-	else {
-		gsize n = G_MAXSIZE;
-
-		nm_hash_update (state, &n, sizeof (n));
-	}
-}
-
-static inline void
-nm_hash_update_str (NMHashState *state, const char *str)
-{
-	nm_assert (str);
-	nm_hash_update (state, str, strlen (str) + 1);
-}
-
-#if _NM_CC_SUPPORT_GENERIC
-/* Like nm_hash_update_str(), but restricted to arrays only. nm_hash_update_str() only works
- * with a @str argument that cannot be NULL. If you have a string pointer, that is never NULL, use
- * nm_hash_update() instead. */
-#define nm_hash_update_strarr(state, str) \
-	(_Generic (&(str), \
-		const char (*) [sizeof (str)]: nm_hash_update_str ((state), (str)), \
-		char (*) [sizeof (str)]:       nm_hash_update_str ((state), (str))) \
-	)
-#else
-#define nm_hash_update_strarr(state, str) nm_hash_update_str ((state), (str))
-#endif
-
-guint nm_hash_ptr (gconstpointer ptr);
-guint nm_direct_hash (gconstpointer str);
-
-guint nm_hash_str (const char *str);
-guint nm_str_hash (gconstpointer str);
-
-#define nm_hash_val(static_seed, val) \
-	({ \
-		NMHashState _h; \
-		\
-		nm_hash_init (&_h, (static_seed)); \
-		nm_hash_update_val (&_h, (val)); \
-		nm_hash_complete (&_h); \
-	})
-
-/*****************************************************************************/
-
-/* nm_pstr_*() are for hashing keys that are pointers to strings,
- * that is, "const char *const*" types, using strcmp(). */
-
-guint nm_pstr_hash (gconstpointer p);
-
-gboolean nm_pstr_equal (gconstpointer a, gconstpointer b);
-
-/*****************************************************************************/
-
-#endif /* __NM_HASH_UTILS_H__ */
diff --git a/shared/nm-utils/nm-io-utils.c b/shared/nm-utils/nm-io-utils.c
deleted file mode 100644
index 51312748..00000000
--- a/shared/nm-utils/nm-io-utils.c
+++ /dev/null
@@ -1,439 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-/* NetworkManager -- Network link manager
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA.
- *
- * (C) Copyright 2018 Red Hat, Inc.
- */
-
-#include "nm-default.h"
-
-#include "nm-io-utils.h"
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#include "nm-shared-utils.h"
-#include "nm-secret-utils.h"
-#include "nm-errno.h"
-
-/*****************************************************************************/
-
-_nm_printf (3, 4)
-static int
-_get_contents_error (GError **error, int errsv, const char *format, ...)
-{
-	nm_assert (NM_ERRNO_NATIVE (errsv));
-
-	if (error) {
-		gs_free char *msg = NULL;
-		va_list args;
-		char bstrerr[NM_STRERROR_BUFSIZE];
-
-		va_start (args, format);
-		msg = g_strdup_vprintf (format, args);
-		va_end (args);
-		g_set_error (error,
-		             G_FILE_ERROR,
-		             g_file_error_from_errno (errsv),
-		             "%s: %s",
-		             msg,
-		             nm_strerror_native_r (errsv, bstrerr, sizeof (bstrerr)));
-	}
-	return -errsv;
-}
-#define _get_contents_error_errno(error, ...) \
-	({ \
-		int _errsv = (errno); \
-		\
-		_get_contents_error (error, _errsv, __VA_ARGS__); \
-	})
-
-static char *
-_mem_realloc (char *old, gboolean do_bzero_mem, gsize cur_len, gsize new_len)
-{
-	char *new;
-
-	/* re-allocating to zero bytes is an odd case. We don't need it
-	 * and it's not supported. */
-	nm_assert (new_len > 0);
-
-	/* regardless of success/failure, @old will always be freed/consumed. */
-
-	if (do_bzero_mem && cur_len > 0) {
-		new = g_try_malloc (new_len);
-		if (new)
-			memcpy (new, old, NM_MIN (cur_len, new_len));
-		nm_explicit_bzero (old, cur_len);
-		g_free (old);
-	} else {
-		new = g_try_realloc (old, new_len);
-		if (!new)
-			g_free (old);
-	}
-
-	return new;
-}
-
-/**
- * nm_utils_fd_get_contents:
- * @fd: open file descriptor to read. The fd will not be closed,
- *   but don't rely on its state afterwards.
- * @close_fd: if %TRUE, @fd will be closed by the function.
- *  Passing %TRUE here might safe a syscall for dup().
- * @max_length: allocate at most @max_length bytes. If the
- *   file is larger, reading will fail. Set to zero to use
- *   a very large default.
- *   WARNING: @max_length is here to avoid a crash for huge/unlimited files.
- *   For example, stat(/sys/class/net/enp0s25/ifindex) gives a filesize of
- *   4K, although the actual real is small. @max_length is the memory
- *   allocated in the process of reading the file, thus it must be at least
- *   the size reported by fstat.
- *   If you set it to 1K, read will fail because fstat() claims the
- *   file is larger.
- * @flags: %NMUtilsFileGetContentsFlags for reading the file.
- * @contents: the output buffer with the file read. It is always
- *   NUL terminated. The buffer is at most @max_length long, including
- *  the NUL byte. That is, it reads only files up to a length of
- *  @max_length - 1 bytes.
- * @length: optional output argument of the read file size.
- *
- * A reimplementation of g_file_get_contents() with a few differences:
- *   - accepts an open fd, instead of a path name. This allows you to
- *     use openat().
- *   - limits the maximum filesize to max_length.
- *
- * Returns: a negative error code on failure.
- */
-int
-nm_utils_fd_get_contents (int fd,
-                          gboolean close_fd,
-                          gsize max_length,
-                          NMUtilsFileGetContentsFlags flags,
-                          char **contents,
-                          gsize *length,
-                          GError **error)
-{
-	nm_auto_close int fd_keeper = close_fd ? fd : -1;
-	struct stat stat_buf;
-	gs_free char *str = NULL;
-	const bool do_bzero_mem = NM_FLAGS_HAS (flags, NM_UTILS_FILE_GET_CONTENTS_FLAG_SECRET);
-	int errsv;
-
-	g_return_val_if_fail (fd >= 0, -EINVAL);
-	g_return_val_if_fail (contents, -EINVAL);
-	g_return_val_if_fail (!error || !*error, -EINVAL);
-
-	if (fstat (fd, &stat_buf) < 0)
-		return _get_contents_error_errno (error, "failure during fstat");
-
-	if (!max_length) {
-		/* default to a very large size, but not extreme */
-		max_length = 2 * 1024 * 1024;
-	}
-
-	if (   stat_buf.st_size > 0
-	    && S_ISREG (stat_buf.st_mode)) {
-		const gsize n_stat = stat_buf.st_size;
-		ssize_t n_read;
-
-		if (n_stat > max_length - 1)
-			return _get_contents_error (error, EMSGSIZE, "file too large (%zu+1 bytes with maximum %zu bytes)", n_stat, max_length);
-
-		str = g_try_malloc (n_stat + 1);
-		if (!str)
-			return _get_contents_error (error, ENOMEM, "failure to allocate buffer of %zu+1 bytes", n_stat);
-
-		n_read = nm_utils_fd_read_loop (fd, str, n_stat, TRUE);
-		if (n_read < 0) {
-			if (do_bzero_mem)
-				nm_explicit_bzero (str, n_stat);
-			return _get_contents_error (error, -n_read, "error reading %zu bytes from file descriptor", n_stat);
-		}
-		str[n_read] = '\0';
-
-		if (n_read < n_stat) {
-			if (!(str = _mem_realloc (str, do_bzero_mem, n_stat + 1, n_read + 1)))
-				return _get_contents_error (error, ENOMEM, "failure to reallocate buffer with %zu bytes", n_read + 1);
-		}
-		NM_SET_OUT (length, n_read);
-	} else {
-		nm_auto_fclose FILE *f = NULL;
-		char buf[4096];
-		gsize n_have, n_alloc;
-		int fd2;
-
-		if (fd_keeper >= 0)
-			fd2 = nm_steal_fd (&fd_keeper);
-		else {
-			fd2 = fcntl (fd, F_DUPFD_CLOEXEC, 0);
-			if (fd2 < 0)
-				return _get_contents_error_errno (error, "error during dup");
-		}
-
-		if (!(f = fdopen (fd2, "r"))) {
-			errsv = errno;
-			nm_close (fd2);
-			return _get_contents_error (error, errsv, "failure during fdopen");
-		}
-
-		n_have = 0;
-		n_alloc = 0;
-
-		while (!feof (f)) {
-			gsize n_read;
-
-			n_read = fread (buf, 1, sizeof (buf), f);
-			errsv = errno;
-			if (ferror (f)) {
-				if (do_bzero_mem)
-					nm_explicit_bzero (buf, sizeof (buf));
-				return _get_contents_error (error, errsv, "error during fread");
-			}
-
-			if (   n_have > G_MAXSIZE - 1 - n_read
-			    || n_have + n_read + 1 > max_length) {
-				if (do_bzero_mem)
-					nm_explicit_bzero (buf, sizeof (buf));
-				return _get_contents_error (error, EMSGSIZE, "file stream too large (%zu+1 bytes with maximum %zu bytes)",
-				                            (n_have > G_MAXSIZE - 1 - n_read) ? G_MAXSIZE : n_have + n_read,
-				                            max_length);
-			}
-
-			if (n_have + n_read + 1 >= n_alloc) {
-				gsize old_n_alloc = n_alloc;
-
-				if (n_alloc != 0) {
-					nm_assert (str);
-					if (n_alloc >= max_length / 2)
-						n_alloc = max_length;
-					else
-						n_alloc *= 2;
-				} else {
-					nm_assert (!str);
-					n_alloc = NM_MIN (n_read + 1, sizeof (buf));
-				}
-
-				if (!(str = _mem_realloc (str, do_bzero_mem, old_n_alloc, n_alloc))) {
-					if (do_bzero_mem)
-						nm_explicit_bzero (buf, sizeof (buf));
-					return _get_contents_error (error, ENOMEM, "failure to allocate buffer of %zu bytes", n_alloc);
-				}
-			}
-
-			memcpy (str + n_have, buf, n_read);
-			n_have += n_read;
-		}
-
-		if (do_bzero_mem)
-			nm_explicit_bzero (buf, sizeof (buf));
-
-		if (n_alloc == 0)
-			str = g_new0 (char, 1);
-		else {
-			str[n_have] = '\0';
-			if (n_have + 1 < n_alloc) {
-				if (!(str = _mem_realloc (str, do_bzero_mem, n_alloc, n_have + 1)))
-					return _get_contents_error (error, ENOMEM, "failure to truncate buffer to %zu bytes", n_have + 1);
-			}
-		}
-
-		NM_SET_OUT (length, n_have);
-	}
-
-	*contents = g_steal_pointer (&str);
-	return 0;
-}
-
-/**
- * nm_utils_file_get_contents:
- * @dirfd: optional file descriptor to use openat(). If negative, use plain open().
- * @filename: the filename to open. Possibly relative to @dirfd.
- * @max_length: allocate at most @max_length bytes.
- *   WARNING: see nm_utils_fd_get_contents() hint about @max_length.
- * @flags: %NMUtilsFileGetContentsFlags for reading the file.
- * @contents: the output buffer with the file read. It is always
- *   NUL terminated. The buffer is at most @max_length long, including
- *   the NUL byte. That is, it reads only files up to a length of
- *   @max_length - 1 bytes.
- * @length: optional output argument of the read file size.
- *
- * A reimplementation of g_file_get_contents() with a few differences:
- *   - accepts an @dirfd to open @filename relative to that path via openat().
- *   - limits the maximum filesize to max_length.
- *   - uses O_CLOEXEC on internal file descriptor
- *
- * Returns: a negative error code on failure.
- */
-int
-nm_utils_file_get_contents (int dirfd,
-                            const char *filename,
-                            gsize max_length,
-                            NMUtilsFileGetContentsFlags flags,
-                            char **contents,
-                            gsize *length,
-                            GError **error)
-{
-	int fd;
-	int errsv;
-	char bstrerr[NM_STRERROR_BUFSIZE];
-
-	g_return_val_if_fail (filename && filename[0], -EINVAL);
-
-	if (dirfd >= 0) {
-		fd = openat (dirfd, filename, O_RDONLY | O_CLOEXEC);
-		if (fd < 0) {
-			errsv = errno;
-
-			g_set_error (error,
-			             G_FILE_ERROR,
-			             g_file_error_from_errno (errsv),
-			             "Failed to open file \"%s\" with openat: %s",
-			             filename,
-			             nm_strerror_native_r (errsv, bstrerr, sizeof (bstrerr)));
-			return -NM_ERRNO_NATIVE (errsv);
-		}
-	} else {
-		fd = open (filename, O_RDONLY | O_CLOEXEC);
-		if (fd < 0) {
-			errsv = errno;
-
-			g_set_error (error,
-			             G_FILE_ERROR,
-			             g_file_error_from_errno (errsv),
-			             "Failed to open file \"%s\": %s",
-			             filename,
-			             nm_strerror_native_r (errsv, bstrerr, sizeof (bstrerr)));
-			return -NM_ERRNO_NATIVE (errsv);
-		}
-	}
-	return nm_utils_fd_get_contents (fd,
-	                                 TRUE,
-	                                 max_length,
-	                                 flags,
-	                                 contents,
-	                                 length,
-	                                 error);
-}
-
-/*****************************************************************************/
-
-/*
- * Copied from GLib's g_file_set_contents() et al., but allows
- * specifying a mode for the new file.
- */
-gboolean
-nm_utils_file_set_contents (const char *filename,
-                            const char *contents,
-                            gssize length,
-                            mode_t mode,
-                            GError **error)
-{
-	gs_free char *tmp_name = NULL;
-	struct stat statbuf;
-	int errsv;
-	gssize s;
-	int fd;
-	char bstrerr[NM_STRERROR_BUFSIZE];
-
-	g_return_val_if_fail (filename, FALSE);
-	g_return_val_if_fail (contents || !length, FALSE);
-	g_return_val_if_fail (!error || !*error, FALSE);
-	g_return_val_if_fail (length >= -1, FALSE);
-
-	if (length == -1)
-		length = strlen (contents);
-
-	tmp_name = g_strdup_printf ("%s.XXXXXX", filename);
-	fd = g_mkstemp_full (tmp_name, O_RDWR | O_CLOEXEC, mode);
-	if (fd < 0) {
-		errsv = errno;
-		g_set_error (error,
-		             G_FILE_ERROR,
-		             g_file_error_from_errno (errsv),
-		             "failed to create file %s: %s",
-		             tmp_name,
-		             nm_strerror_native_r (errsv, bstrerr, sizeof (bstrerr)));
-		return FALSE;
-	}
-
-	while (length > 0) {
-		s = write (fd, contents, length);
-		if (s < 0) {
-			errsv = errno;
-			if (errsv == EINTR)
-				continue;
-
-			nm_close (fd);
-			unlink (tmp_name);
-
-			g_set_error (error,
-			             G_FILE_ERROR,
-			             g_file_error_from_errno (errsv),
-			             "failed to write to file %s: %s",
-			             tmp_name,
-			             nm_strerror_native_r (errsv, bstrerr, sizeof (bstrerr)));
-			return FALSE;
-		}
-
-		g_assert (s <= length);
-
-		contents += s;
-		length -= s;
-	}
-
-	/* If the final destination exists and is > 0 bytes, we want to sync the
-	 * newly written file to ensure the data is on disk when we rename over
-	 * the destination. Otherwise if we get a system crash we can lose both
-	 * the new and the old file on some filesystems. (I.E. those that don't
-	 * guarantee the data is written to the disk before the metadata.)
-	 */
-	if (   lstat (filename, &statbuf) == 0
-	    && statbuf.st_size > 0) {
-		if (fsync (fd) != 0) {
-			errsv = errno;
-
-			nm_close (fd);
-			unlink (tmp_name);
-
-			g_set_error (error,
-			             G_FILE_ERROR,
-			             g_file_error_from_errno (errsv),
-			             "failed to fsync %s: %s",
-			             tmp_name,
-			             nm_strerror_native_r (errsv, bstrerr, sizeof (bstrerr)));
-			return FALSE;
-		}
-	}
-
-	nm_close (fd);
-
-	if (rename (tmp_name, filename)) {
-		errsv = errno;
-		unlink (tmp_name);
-		g_set_error (error,
-		             G_FILE_ERROR,
-		             g_file_error_from_errno (errsv),
-		             "failed to rename %s to %s: %s",
-		             tmp_name,
-		             filename,
-		             nm_strerror_native_r (errsv, bstrerr, sizeof (bstrerr)));
-		return FALSE;
-	}
-
-	return TRUE;
-}
diff --git a/shared/nm-utils/nm-io-utils.h b/shared/nm-utils/nm-io-utils.h
deleted file mode 100644
index dc72a2a6..00000000
--- a/shared/nm-utils/nm-io-utils.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-/* NetworkManager -- Network link manager
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA.
- *
- * (C) Copyright 2018 Red Hat, Inc.
- */
-
-#ifndef __NM_IO_UTILS_H__
-#define __NM_IO_UTILS_H__
-
-#include "nm-macros-internal.h"
-
-/*****************************************************************************/
-
-/**
- * NMUtilsFileGetContentsFlags:
- * @NM_UTILS_FILE_GET_CONTENTS_FLAG_NONE: no flag
- * @NM_UTILS_FILE_GET_CONTENTS_FLAG_SECRET: if present, ensure that no
- *   data is left in memory. Essentially, it means to call explicity_bzero()
- *   to not leave key material on the heap (when reading secrets).
- */
-typedef enum {
-	NM_UTILS_FILE_GET_CONTENTS_FLAG_NONE   = 0,
-	NM_UTILS_FILE_GET_CONTENTS_FLAG_SECRET = (1 << 0),
-} NMUtilsFileGetContentsFlags;
-
-int nm_utils_fd_get_contents (int fd,
-                              gboolean close_fd,
-                              gsize max_length,
-                              NMUtilsFileGetContentsFlags flags,
-                              char **contents,
-                              gsize *length,
-                              GError **error);
-
-int nm_utils_file_get_contents (int dirfd,
-                                const char *filename,
-                                gsize max_length,
-                                NMUtilsFileGetContentsFlags flags,
-                                char **contents,
-                                gsize *length,
-                                GError **error);
-
-gboolean nm_utils_file_set_contents (const char *filename,
-                                     const char *contents,
-                                     gssize length,
-                                     mode_t mode,
-                                     GError **error);
-
-#endif /* __NM_IO_UTILS_H__ */
diff --git a/shared/nm-utils/nm-jansson.h b/shared/nm-utils/nm-jansson.h
deleted file mode 100644
index 5a73231f..00000000
--- a/shared/nm-utils/nm-jansson.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Copyright 2018 Red Hat, Inc.
- */
-
-#ifndef __NM_JANSSON_H__
-#define __NM_JANSSON_H__
-
-/* you need to include at least "config.h" first, possibly "nm-default.h". */
-
-#if WITH_JANSSON
-
-#include <jansson.h>
-
-/* Added in Jansson v2.7 */
-#ifndef json_boolean_value
-#define json_boolean_value json_is_true
-#endif
-
-/* Added in Jansson v2.8 */
-#ifndef json_object_foreach_safe
-#define json_object_foreach_safe(object, n, key, value)     \
-    for (key = json_object_iter_key(json_object_iter(object)), \
-             n = json_object_iter_next(object, json_object_key_to_iter(key)); \
-         key && (value = json_object_iter_value(json_object_key_to_iter(key))); \
-         key = json_object_iter_key(n), \
-             n = json_object_iter_next(object, json_object_key_to_iter(key)))
-#endif
-
-NM_AUTO_DEFINE_FCN0 (json_t *, _nm_auto_decref_json, json_decref)
-#define nm_auto_decref_json nm_auto(_nm_auto_decref_json)
-
-#endif /* WITH_JANSON */
-
-#endif  /* __NM_JANSSON_H__ */
diff --git a/shared/nm-utils/nm-logging-fwd.h b/shared/nm-utils/nm-logging-fwd.h
deleted file mode 100644
index 900dfff8..00000000
--- a/shared/nm-utils/nm-logging-fwd.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/* NetworkManager -- Network link manager
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA.
- *
- * Copyright (C) 2006 - 2018 Red Hat, Inc.
- * Copyright (C) 2006 - 2008 Novell, Inc.
- */
-
-#ifndef __NM_LOGGING_DEFINES_H__
-#define __NM_LOGGING_DEFINES_H__
-
-/* Log domains */
-
-typedef enum  { /*< skip >*/
-	LOGD_NONE       = 0LL,
-	LOGD_PLATFORM   = (1LL << 0), /* Platform services */
-	LOGD_RFKILL     = (1LL << 1),
-	LOGD_ETHER      = (1LL << 2),
-	LOGD_WIFI       = (1LL << 3),
-	LOGD_BT         = (1LL << 4),
-	LOGD_MB         = (1LL << 5), /* mobile broadband */
-	LOGD_DHCP4      = (1LL << 6),
-	LOGD_DHCP6      = (1LL << 7),
-	LOGD_PPP        = (1LL << 8),
-	LOGD_WIFI_SCAN  = (1LL << 9),
-	LOGD_IP4        = (1LL << 10),
-	LOGD_IP6        = (1LL << 11),
-	LOGD_AUTOIP4    = (1LL << 12),
-	LOGD_DNS        = (1LL << 13),
-	LOGD_VPN        = (1LL << 14),
-	LOGD_SHARING    = (1LL << 15), /* Connection sharing/dnsmasq */
-	LOGD_SUPPLICANT = (1LL << 16), /* Wi-Fi and 802.1x */
-	LOGD_AGENTS     = (1LL << 17), /* Secret agents */
-	LOGD_SETTINGS   = (1LL << 18), /* Settings */
-	LOGD_SUSPEND    = (1LL << 19), /* Suspend/Resume */
-	LOGD_CORE       = (1LL << 20), /* Core daemon and policy stuff */
-	LOGD_DEVICE     = (1LL << 21), /* Device state and activation */
-	LOGD_OLPC       = (1LL << 22),
-	LOGD_INFINIBAND = (1LL << 23),
-	LOGD_FIREWALL   = (1LL << 24),
-	LOGD_ADSL       = (1LL << 25),
-	LOGD_BOND       = (1LL << 26),
-	LOGD_VLAN       = (1LL << 27),
-	LOGD_BRIDGE     = (1LL << 28),
-	LOGD_DBUS_PROPS = (1LL << 29),
-	LOGD_TEAM       = (1LL << 30),
-	LOGD_CONCHECK   = (1LL << 31),
-	LOGD_DCB        = (1LL << 32), /* Data Center Bridging */
-	LOGD_DISPATCH   = (1LL << 33),
-	LOGD_AUDIT      = (1LL << 34),
-	LOGD_SYSTEMD    = (1LL << 35),
-	LOGD_VPN_PLUGIN = (1LL << 36),
-	LOGD_PROXY      = (1LL << 37),
-
-	__LOGD_MAX,
-	LOGD_ALL       = (((__LOGD_MAX - 1LL) << 1) - 1LL),
-	LOGD_DEFAULT   = LOGD_ALL & ~(
-	                              LOGD_DBUS_PROPS |
-	                              LOGD_WIFI_SCAN |
-	                              LOGD_VPN_PLUGIN |
-	                              0),
-
-	/* aliases: */
-	LOGD_DHCP       = LOGD_DHCP4 | LOGD_DHCP6,
-	LOGD_IP         = LOGD_IP4 | LOGD_IP6,
-} NMLogDomain;
-
-/* Log levels */
-typedef enum  { /*< skip >*/
-	LOGL_TRACE,
-	LOGL_DEBUG,
-	LOGL_INFO,
-	LOGL_WARN,
-	LOGL_ERR,
-
-	_LOGL_N_REAL, /* the number of actual logging levels */
-
-	_LOGL_OFF = _LOGL_N_REAL, /* special logging level that is always disabled. */
-	_LOGL_KEEP,               /* special logging level to indicate that the logging level should not be changed. */
-
-	_LOGL_N, /* the number of logging levels including "OFF" */
-} NMLogLevel;
-
-gboolean _nm_log_enabled_impl (gboolean mt_require_locking,
-                               NMLogLevel level,
-                               NMLogDomain domain);
-
-void _nm_log_impl (const char *file,
-                   guint line,
-                   const char *func,
-                   gboolean mt_require_locking,
-                   NMLogLevel level,
-                   NMLogDomain domain,
-                   int error,
-                   const char *ifname,
-                   const char *con_uuid,
-                   const char *fmt,
-                   ...) _nm_printf (10, 11);
-
-#endif /* __NM_LOGGING_DEFINES_H__ */
diff --git a/shared/nm-utils/nm-macros-internal.h b/shared/nm-utils/nm-macros-internal.h
deleted file mode 100644
index 42299c96..00000000
--- a/shared/nm-utils/nm-macros-internal.h
+++ /dev/null
@@ -1,1707 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-/* NetworkManager -- Network link manager
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA.
- *
- * (C) Copyright 2012 Colin Walters <walters@verbum.org>.
- * (C) Copyright 2014 Red Hat, Inc.
- */
-
-#ifndef __NM_MACROS_INTERNAL_H__
-#define __NM_MACROS_INTERNAL_H__
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-
-#include <gio/gio.h>
-
-/*****************************************************************************/
-
-#define _nm_packed           __attribute__ ((__packed__))
-#define _nm_unused           __attribute__ ((__unused__))
-#define _nm_used             __attribute__ ((__used__))
-#define _nm_pure             __attribute__ ((__pure__))
-#define _nm_const            __attribute__ ((__const__))
-#define _nm_printf(a,b)      __attribute__ ((__format__ (__printf__, a, b)))
-#define _nm_align(s)         __attribute__ ((__aligned__ (s)))
-#define _nm_section(s)       __attribute__ ((__section__ (s)))
-#define _nm_alignof(type)    __alignof (type)
-#define _nm_alignas(type)    _nm_align (_nm_alignof (type))
-#define nm_auto(fcn)         __attribute__ ((__cleanup__(fcn)))
-
-
-/* This is required to make LTO working.
- *
- * See https://gitlab.freedesktop.org/NetworkManager/NetworkManager/merge_requests/76#note_112694
- *     https://gcc.gnu.org/bugzilla/show_bug.cgi?id=48200#c28
- */
-#ifndef __clang__
-#define _nm_externally_visible __attribute__ ((__externally_visible__))
-#else
-#define _nm_externally_visible
-#endif
-
-
-#if __GNUC__ >= 7
-#define _nm_fallthrough      __attribute__ ((__fallthrough__))
-#else
-#define _nm_fallthrough
-#endif
-
-/*****************************************************************************/
-
-#ifdef thread_local
-#define _nm_thread_local thread_local
-/*
- * Don't break on glibc < 2.16 that doesn't define __STDC_NO_THREADS__
- * see http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53769
- */
-#elif __STDC_VERSION__ >= 201112L && !(defined(__STDC_NO_THREADS__) || (defined(__GNU_LIBRARY__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 16))
-#define _nm_thread_local _Thread_local
-#else
-#define _nm_thread_local __thread
-#endif
-
-/*****************************************************************************/
-
-/* most of our code is single-threaded with a mainloop. Hence, we usually don't need
- * any thread-safety. Sometimes, we do need thread-safety (nm-logging), but we can
- * avoid locking if we are on the main-thread by:
- *
- *   - modifications of shared data is done infrequently and only from the
- *     main-thread (nm_logging_setup())
- *   - read-only access is done frequently (nm_logging_enabled())
- *     - from the main-thread, we can do that without locking (because
- *       all modifications are also done on the main thread.
- *     - from other threads, we need locking. But this is expected to be
- *       done infrequently too. Important is the lock-free fast-path on the
- *       main-thread.
- *
- * By defining NM_THREAD_SAFE_ON_MAIN_THREAD you indicate that this code runs
- * on the main-thread. It is by default defined to "1". If you have code that
- * is also used on another thread, redefine the define to 0 (to opt in into
- * the slow-path).
- */
-#define NM_THREAD_SAFE_ON_MAIN_THREAD 1
-
-/*****************************************************************************/
-
-#define NM_AUTO_DEFINE_FCN_VOID(CastType, name, func) \
-static inline void name (void *v) \
-{ \
-	func (*((CastType *) v)); \
-}
-
-#define NM_AUTO_DEFINE_FCN_VOID0(CastType, name, func) \
-static inline void name (void *v) \
-{ \
-	if (*((CastType *) v)) \
-		func (*((CastType *) v)); \
-}
-
-#define NM_AUTO_DEFINE_FCN(Type, name, func) \
-static inline void name (Type *v) \
-{ \
-	func (*v); \
-}
-
-#define NM_AUTO_DEFINE_FCN0(Type, name, func) \
-static inline void name (Type *v) \
-{ \
-	if (*v) \
-		func (*v); \
-}
-
-/*****************************************************************************/
-
-/**
- * gs_free:
- *
- * Call g_free() on a variable location when it goes out of scope.
- */
-#define gs_free nm_auto(gs_local_free)
-NM_AUTO_DEFINE_FCN_VOID0 (void *, gs_local_free, g_free)
-
-/**
- * gs_unref_object:
- *
- * Call g_object_unref() on a variable location when it goes out of
- * scope.  Note that unlike g_object_unref(), the variable may be
- * %NULL.
- */
-#define gs_unref_object nm_auto(gs_local_obj_unref)
-NM_AUTO_DEFINE_FCN_VOID0 (GObject *, gs_local_obj_unref, g_object_unref)
-
-/**
- * gs_unref_variant:
- *
- * Call g_variant_unref() on a variable location when it goes out of
- * scope.  Note that unlike g_variant_unref(), the variable may be
- * %NULL.
- */
-#define gs_unref_variant nm_auto(gs_local_variant_unref)
-NM_AUTO_DEFINE_FCN0 (GVariant *, gs_local_variant_unref, g_variant_unref)
-
-/**
- * gs_unref_array:
- *
- * Call g_array_unref() on a variable location when it goes out of
- * scope.  Note that unlike g_array_unref(), the variable may be
- * %NULL.
-
- */
-#define gs_unref_array nm_auto(gs_local_array_unref)
-NM_AUTO_DEFINE_FCN0 (GArray *, gs_local_array_unref, g_array_unref)
-
-/**
- * gs_unref_ptrarray:
- *
- * Call g_ptr_array_unref() on a variable location when it goes out of
- * scope.  Note that unlike g_ptr_array_unref(), the variable may be
- * %NULL.
-
- */
-#define gs_unref_ptrarray nm_auto(gs_local_ptrarray_unref)
-NM_AUTO_DEFINE_FCN0 (GPtrArray *, gs_local_ptrarray_unref, g_ptr_array_unref)
-
-/**
- * gs_unref_hashtable:
- *
- * Call g_hash_table_unref() on a variable location when it goes out
- * of scope.  Note that unlike g_hash_table_unref(), the variable may
- * be %NULL.
- */
-#define gs_unref_hashtable nm_auto(gs_local_hashtable_unref)
-NM_AUTO_DEFINE_FCN0 (GHashTable *, gs_local_hashtable_unref, g_hash_table_unref)
-
-/**
- * gs_free_slist:
- *
- * Call g_slist_free() on a variable location when it goes out
- * of scope.
- */
-#define gs_free_slist nm_auto(gs_local_free_slist)
-NM_AUTO_DEFINE_FCN0 (GSList *, gs_local_free_slist, g_slist_free)
-
-/**
- * gs_unref_bytes:
- *
- * Call g_bytes_unref() on a variable location when it goes out
- * of scope.  Note that unlike g_bytes_unref(), the variable may
- * be %NULL.
- */
-#define gs_unref_bytes nm_auto(gs_local_bytes_unref)
-NM_AUTO_DEFINE_FCN0 (GBytes *, gs_local_bytes_unref, g_bytes_unref)
-
-/**
- * gs_strfreev:
- *
- * Call g_strfreev() on a variable location when it goes out of scope.
- */
-#define gs_strfreev nm_auto(gs_local_strfreev)
-NM_AUTO_DEFINE_FCN0 (char **, gs_local_strfreev, g_strfreev)
-
-/**
- * gs_free_error:
- *
- * Call g_error_free() on a variable location when it goes out of scope.
- */
-#define gs_free_error nm_auto(gs_local_free_error)
-NM_AUTO_DEFINE_FCN0 (GError *, gs_local_free_error, g_error_free)
-
-/**
- * gs_unref_keyfile:
- *
- * Call g_key_file_unref() on a variable location when it goes out of scope.
- */
-#define gs_unref_keyfile nm_auto(gs_local_keyfile_unref)
-NM_AUTO_DEFINE_FCN0 (GKeyFile *, gs_local_keyfile_unref, g_key_file_unref)
-
-/*****************************************************************************/
-
-#include "nm-glib.h"
-
-/*****************************************************************************/
-
-#define nm_offsetofend(t,m) (G_STRUCT_OFFSET (t,m) + sizeof (((t *) NULL)->m))
-
-/*****************************************************************************/
-
-static inline int nm_close (int fd);
-
-/**
- * nm_auto_free:
- *
- * Call free() on a variable location when it goes out of scope.
- * This is for pointers that are allocated with malloc() instead of
- * g_malloc().
- *
- * In practice, since glib 2.45, g_malloc()/g_free() always wraps malloc()/free().
- * See bgo#751592. In that case, it would be safe to free pointers allocated with
- * malloc() with gs_free or g_free().
- *
- * However, let's never mix them. To free malloc'ed memory, always use
- * free() or nm_auto_free.
- */
-NM_AUTO_DEFINE_FCN_VOID0 (void *, _nm_auto_free_impl, free)
-#define nm_auto_free nm_auto(_nm_auto_free_impl)
-
-NM_AUTO_DEFINE_FCN0 (GVariantIter *, _nm_auto_free_variant_iter, g_variant_iter_free)
-#define nm_auto_free_variant_iter nm_auto(_nm_auto_free_variant_iter)
-
-NM_AUTO_DEFINE_FCN0 (GVariantBuilder *, _nm_auto_unref_variant_builder, g_variant_builder_unref)
-#define nm_auto_unref_variant_builder nm_auto(_nm_auto_unref_variant_builder)
-
-NM_AUTO_DEFINE_FCN0 (GList *, _nm_auto_free_list, g_list_free)
-#define nm_auto_free_list nm_auto(_nm_auto_free_list)
-
-NM_AUTO_DEFINE_FCN0 (GChecksum *, _nm_auto_checksum_free, g_checksum_free)
-#define nm_auto_free_checksum nm_auto(_nm_auto_checksum_free)
-
-#define nm_auto_unset_gvalue nm_auto(g_value_unset)
-
-NM_AUTO_DEFINE_FCN_VOID0 (void *, _nm_auto_unref_gtypeclass, g_type_class_unref)
-#define nm_auto_unref_gtypeclass nm_auto(_nm_auto_unref_gtypeclass)
-
-NM_AUTO_DEFINE_FCN0 (GByteArray *, _nm_auto_unref_bytearray, g_byte_array_unref)
-#define nm_auto_unref_bytearray nm_auto(_nm_auto_unref_bytearray)
-
-static inline void
-_nm_auto_free_gstring (GString **str)
-{
-	if (*str)
-		g_string_free (*str, TRUE);
-}
-#define nm_auto_free_gstring nm_auto(_nm_auto_free_gstring)
-
-static inline void
-_nm_auto_close (int *pfd)
-{
-	if (*pfd >= 0) {
-		int errsv = errno;
-
-		(void) nm_close (*pfd);
-		errno = errsv;
-	}
-}
-#define nm_auto_close nm_auto(_nm_auto_close)
-
-static inline void
-_nm_auto_fclose (FILE **pfd)
-{
-	if (*pfd) {
-		int errsv = errno;
-
-		(void) fclose (*pfd);
-		errno = errsv;
-	}
-}
-#define nm_auto_fclose nm_auto(_nm_auto_fclose)
-
-static inline void
-_nm_auto_protect_errno (int *p_saved_errno)
-{
-	errno = *p_saved_errno;
-}
-#define NM_AUTO_PROTECT_ERRNO(errsv_saved) nm_auto(_nm_auto_protect_errno) _nm_unused const int errsv_saved = (errno)
-
-NM_AUTO_DEFINE_FCN0 (GSource *, _nm_auto_unref_gsource, g_source_unref);
-#define nm_auto_unref_gsource nm_auto(_nm_auto_unref_gsource)
-
-static inline void
-_nm_auto_freev (gpointer ptr)
-{
-	gpointer **p = ptr;
-	gpointer *_ptr;
-
-	if (*p) {
-		for (_ptr = *p; *_ptr; _ptr++)
-			g_free (*_ptr);
-		g_free (*p);
-	}
-}
-/* g_free a NULL terminated array of pointers, with also freeing each
- * pointer with g_free(). It essentially does the same as
- * gs_strfreev / g_strfreev(), but not restricted to strv arrays. */
-#define nm_auto_freev nm_auto(_nm_auto_freev)
-
-/*****************************************************************************/
-
-/* http://stackoverflow.com/a/11172679 */
-#define  _NM_UTILS_MACRO_FIRST(...)                           __NM_UTILS_MACRO_FIRST_HELPER(__VA_ARGS__, throwaway)
-#define __NM_UTILS_MACRO_FIRST_HELPER(first, ...)             first
-
-#define  _NM_UTILS_MACRO_REST(...)                            __NM_UTILS_MACRO_REST_HELPER(__NM_UTILS_MACRO_REST_NUM(__VA_ARGS__), __VA_ARGS__)
-#define __NM_UTILS_MACRO_REST_HELPER(qty, ...)                __NM_UTILS_MACRO_REST_HELPER2(qty, __VA_ARGS__)
-#define __NM_UTILS_MACRO_REST_HELPER2(qty, ...)               __NM_UTILS_MACRO_REST_HELPER_##qty(__VA_ARGS__)
-#define __NM_UTILS_MACRO_REST_HELPER_ONE(first)
-#define __NM_UTILS_MACRO_REST_HELPER_TWOORMORE(first, ...)    , __VA_ARGS__
-#define __NM_UTILS_MACRO_REST_NUM(...) \
-    __NM_UTILS_MACRO_REST_SELECT_30TH(__VA_ARGS__, \
-                TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE,\
-                TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE,\
-                TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE,\
-                TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE,\
-                TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE,\
-                TWOORMORE, TWOORMORE, TWOORMORE, ONE, throwaway)
-#define __NM_UTILS_MACRO_REST_SELECT_30TH(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, ...) a30
-
-/*****************************************************************************/
-
-/* http://stackoverflow.com/a/2124385/354393
- * https://stackoverflow.com/questions/11317474/macro-to-count-number-of-arguments
- */
-
-#define NM_NARG(...) \
-         _NM_NARG(, ##__VA_ARGS__, _NM_NARG_RSEQ_N())
-#define _NM_NARG(...) \
-         _NM_NARG_ARG_N(__VA_ARGS__)
-#define _NM_NARG_ARG_N( \
-          _0, \
-          _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
-         _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
-         _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
-         _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
-         _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
-         _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
-         _61,_62,_63,N,...) N
-#define _NM_NARG_RSEQ_N() \
-         63,62,61,60,                   \
-         59,58,57,56,55,54,53,52,51,50, \
-         49,48,47,46,45,44,43,42,41,40, \
-         39,38,37,36,35,34,33,32,31,30, \
-         29,28,27,26,25,24,23,22,21,20, \
-         19,18,17,16,15,14,13,12,11,10, \
-         9,8,7,6,5,4,3,2,1,0
-
-/*****************************************************************************/
-
-#if defined (__GNUC__)
-#define _NM_PRAGMA_WARNING_DO(warning)       G_STRINGIFY(GCC diagnostic ignored warning)
-#elif defined (__clang__)
-#define _NM_PRAGMA_WARNING_DO(warning)       G_STRINGIFY(clang diagnostic ignored warning)
-#endif
-
-/* you can only suppress a specific warning that the compiler
- * understands. Otherwise you will get another compiler warning
- * about invalid pragma option.
- * It's not that bad however, because gcc and clang often have the
- * same name for the same warning. */
-
-#if defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
-#define NM_PRAGMA_WARNING_DISABLE(warning) \
-        _Pragma("GCC diagnostic push") \
-        _Pragma(_NM_PRAGMA_WARNING_DO(warning))
-#elif defined (__clang__)
-#define NM_PRAGMA_WARNING_DISABLE(warning) \
-        _Pragma("clang diagnostic push") \
-        _Pragma(_NM_PRAGMA_WARNING_DO("-Wunknown-warning-option")) \
-        _Pragma(_NM_PRAGMA_WARNING_DO(warning))
-#else
-#define NM_PRAGMA_WARNING_DISABLE(warning)
-#endif
-
-#if defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
-#define NM_PRAGMA_WARNING_REENABLE \
-    _Pragma("GCC diagnostic pop")
-#elif defined (__clang__)
-#define NM_PRAGMA_WARNING_REENABLE \
-    _Pragma("clang diagnostic pop")
-#else
-#define NM_PRAGMA_WARNING_REENABLE
-#endif
-
-/*****************************************************************************/
-
-/**
- * NM_G_ERROR_MSG:
- * @error: (allow-none): the #GError instance
- *
- * All functions must follow the convention that when they
- * return a failure, they must also set the GError to a valid
- * message. For external API however, we want to be extra
- * careful before accessing the error instance. Use NM_G_ERROR_MSG()
- * which is safe to use on NULL.
- *
- * Returns: the error message.
- **/
-static inline const char *
-NM_G_ERROR_MSG (GError *error)
-{
-	return error ? (error->message ?: "(null)") : "(no-error)"; \
-}
-
-/*****************************************************************************/
-
-/* macro to return strlen() of a compile time string. */
-#define NM_STRLEN(str)     ( sizeof (""str"") - 1 )
-
-/* returns the length of a NULL terminated array of pointers,
- * like g_strv_length() does. The difference is:
- *  - it operats on arrays of pointers (of any kind, requiring no cast).
- *  - it accepts NULL to return zero. */
-#define NM_PTRARRAY_LEN(array) \
-	({ \
-		typeof (*(array)) *const _array = (array); \
-		gsize _n = 0; \
-		\
-		if (_array) { \
-			_nm_unused gconstpointer _type_check_is_pointer = _array[0]; \
-			\
-			while (_array[_n]) \
-				_n++; \
-		} \
-		_n; \
-	})
-
-/* Note: @value is only evaluated when *out_val is present.
- * Thus,
- *    NM_SET_OUT (out_str, g_strdup ("hallo"));
- * does the right thing.
- */
-#define NM_SET_OUT(out_val, value) \
-	G_STMT_START { \
-		typeof(*(out_val)) *_out_val = (out_val); \
-		\
-		if (_out_val) { \
-			*_out_val = (value); \
-		} \
-	} G_STMT_END
-
-/*****************************************************************************/
-
-#ifndef _NM_CC_SUPPORT_AUTO_TYPE
-#if (defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9 )))
-#define _NM_CC_SUPPORT_AUTO_TYPE 1
-#else
-#define _NM_CC_SUPPORT_AUTO_TYPE 0
-#endif
-#endif
-
-#ifndef _NM_CC_SUPPORT_GENERIC
-/* In the meantime, NetworkManager requires C11 and _Generic() should always be available.
- * However, shared/nm-utils may also be used in VPN/applet, which possibly did not yet
- * bump the C standard requirement. Leave this for the moment, but eventually we can
- * drop it. */
-#if (defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9 ))) || (defined (__clang__))
-#define _NM_CC_SUPPORT_GENERIC 1
-#else
-#define _NM_CC_SUPPORT_GENERIC 0
-#endif
-#endif
-
-#if _NM_CC_SUPPORT_AUTO_TYPE
-#define _nm_auto_type __auto_type
-#endif
-
-#if _NM_CC_SUPPORT_GENERIC
-#define _NM_CONSTCAST_FULL_1(type, obj_expr, obj) \
-	(_Generic ((obj_expr), \
-	           const void        *const: ((const type *) (obj)), \
-	           const void        *     : ((const type *) (obj)), \
-	                 void        *const: ((      type *) (obj)), \
-	                 void        *     : ((      type *) (obj)), \
-	           const type        *const: ((const type *) (obj)), \
-	           const type        *     : ((const type *) (obj)), \
-	                 type        *const: ((      type *) (obj)), \
-	                 type        *     : ((      type *) (obj))))
-#define _NM_CONSTCAST_FULL_2(type, obj_expr, obj, alias_type2) \
-	(_Generic ((obj_expr), \
-	           const void        *const: ((const type *) (obj)), \
-	           const void        *     : ((const type *) (obj)), \
-	                 void        *const: ((      type *) (obj)), \
-	                 void        *     : ((      type *) (obj)), \
-	           const alias_type2 *const: ((const type *) (obj)), \
-	           const alias_type2 *     : ((const type *) (obj)), \
-	                 alias_type2 *const: ((      type *) (obj)), \
-	                 alias_type2 *     : ((      type *) (obj)), \
-	           const type        *const: ((const type *) (obj)), \
-	           const type        *     : ((const type *) (obj)), \
-	                 type        *const: ((      type *) (obj)), \
-	                 type        *     : ((      type *) (obj))))
-#define _NM_CONSTCAST_FULL_3(type, obj_expr, obj, alias_type2, alias_type3) \
-	(_Generic ((obj_expr), \
-	           const void        *const: ((const type *) (obj)), \
-	           const void        *     : ((const type *) (obj)), \
-	                 void        *const: ((      type *) (obj)), \
-	                 void        *     : ((      type *) (obj)), \
-	           const alias_type2 *const: ((const type *) (obj)), \
-	           const alias_type2 *     : ((const type *) (obj)), \
-	                 alias_type2 *const: ((      type *) (obj)), \
-	                 alias_type2 *     : ((      type *) (obj)), \
-	           const alias_type3 *const: ((const type *) (obj)), \
-	           const alias_type3 *     : ((const type *) (obj)), \
-	                 alias_type3 *const: ((      type *) (obj)), \
-	                 alias_type3 *     : ((      type *) (obj)), \
-	           const type        *const: ((const type *) (obj)), \
-	           const type        *     : ((const type *) (obj)), \
-	                 type        *const: ((      type *) (obj)), \
-	                 type        *     : ((      type *) (obj))))
-#define _NM_CONSTCAST_FULL_4(type, obj_expr, obj, alias_type2, alias_type3, alias_type4) \
-	(_Generic ((obj_expr), \
-	           const void        *const: ((const type *) (obj)), \
-	           const void        *     : ((const type *) (obj)), \
-	                 void        *const: ((      type *) (obj)), \
-	                 void        *     : ((      type *) (obj)), \
-	           const alias_type2 *const: ((const type *) (obj)), \
-	           const alias_type2 *     : ((const type *) (obj)), \
-	                 alias_type2 *const: ((      type *) (obj)), \
-	                 alias_type2 *     : ((      type *) (obj)), \
-	           const alias_type3 *const: ((const type *) (obj)), \
-	           const alias_type3 *     : ((const type *) (obj)), \
-	                 alias_type3 *const: ((      type *) (obj)), \
-	                 alias_type3 *     : ((      type *) (obj)), \
-	           const alias_type4 *const: ((const type *) (obj)), \
-	           const alias_type4 *     : ((const type *) (obj)), \
-	                 alias_type4 *const: ((      type *) (obj)), \
-	                 alias_type4 *     : ((      type *) (obj)), \
-	           const type        *const: ((const type *) (obj)), \
-	           const type        *     : ((const type *) (obj)), \
-	                 type        *const: ((      type *) (obj)), \
-	                 type        *     : ((      type *) (obj))))
-#define _NM_CONSTCAST_FULL_x(type, obj_expr, obj, n, ...)   (_NM_CONSTCAST_FULL_##n (type, obj_expr, obj,                        ##__VA_ARGS__))
-#define _NM_CONSTCAST_FULL_y(type, obj_expr, obj, n, ...)   (_NM_CONSTCAST_FULL_x   (type, obj_expr, obj, n,                     ##__VA_ARGS__))
-#define NM_CONSTCAST_FULL(   type, obj_expr, obj,    ...)   (_NM_CONSTCAST_FULL_y   (type, obj_expr, obj, NM_NARG (dummy, ##__VA_ARGS__), ##__VA_ARGS__))
-#else
-#define NM_CONSTCAST_FULL(   type, obj_expr, obj,    ...)   ((type *) (obj))
-#endif
-
-#define NM_CONSTCAST(type, obj, ...) \
-	NM_CONSTCAST_FULL(type, (obj), (obj), ##__VA_ARGS__)
-
-#if _NM_CC_SUPPORT_GENERIC
-#define NM_UNCONST_PTR(type, arg) \
-	_Generic ((arg), \
-	          const type *: ((type *) (arg)), \
-	                type *: ((type *) (arg)))
-#else
-#define NM_UNCONST_PTR(type, arg) \
-	((type *) (arg))
-#endif
-
-#if _NM_CC_SUPPORT_GENERIC
-#define NM_UNCONST_PPTR(type, arg) \
-	_Generic ((arg), \
-	          const type *     *: ((type **) (arg)), \
-	                type *     *: ((type **) (arg)), \
-	          const type *const*: ((type **) (arg)), \
-	                type *const*: ((type **) (arg)))
-#else
-#define NM_UNCONST_PPTR(type, arg) \
-	((type **) (arg))
-#endif
-
-#define NM_GOBJECT_CAST(type, obj, is_check, ...) \
-	({ \
-		const void *_obj = (obj); \
-		\
-		nm_assert (_obj || (is_check (_obj))); \
-		NM_CONSTCAST_FULL (type, (obj), _obj, GObject, ##__VA_ARGS__); \
-	})
-
-#define NM_GOBJECT_CAST_NON_NULL(type, obj, is_check, ...) \
-	({ \
-		const void *_obj = (obj); \
-		\
-		nm_assert (is_check (_obj)); \
-		NM_CONSTCAST_FULL (type, (obj), _obj, GObject, ##__VA_ARGS__); \
-	})
-
-#if _NM_CC_SUPPORT_GENERIC
-/* returns @value, if the type of @value matches @type.
- * This requires support for C11 _Generic(). If no support is
- * present, this returns @value directly.
- *
- * It's useful to check the let the compiler ensure that @value is
- * of a certain type. */
-#define _NM_ENSURE_TYPE(type, value) (_Generic ((value), type: (value)))
-#else
-#define _NM_ENSURE_TYPE(type, value) (value)
-#endif
-
-#if _NM_CC_SUPPORT_GENERIC
-/* these macros cast (value) to
- *  - "const char **"      (for "MC", mutable-const)
- *  - "const char *const*" (for "CC", const-const)
- * The point is to do this cast, but only accepting pointers
- * that are compatible already.
- *
- * The problem is, if you add a function like g_strdupv(), the input
- * argument is not modified (CC), but you want to make it work also
- * for "char **". C doesn't allow this form of casting (for good reasons),
- * so the function makes a choice like g_strdupv(char**). That means,
- * every time you want to call it with a const argument, you need to
- * explicitly cast it.
- *
- * These macros do the cast, but they only accept a compatible input
- * type, otherwise they will fail compilation.
- */
-#define NM_CAST_STRV_MC(value) \
-	(_Generic ((value), \
-	           const char *     *: (const char *     *) (value), \
-	                 char *     *: (const char *     *) (value), \
-	                       void *: (const char *     *) (value)))
-#define NM_CAST_STRV_CC(value) \
-	(_Generic ((value), \
-	           const char *const*: (const char *const*) (value), \
-	           const char *     *: (const char *const*) (value), \
-	                 char *const*: (const char *const*) (value), \
-	                 char *     *: (const char *const*) (value), \
-	                 const void *: (const char *const*) (value), \
-	                       void *: (const char *const*) (value)))
-#else
-#define NM_CAST_STRV_MC(value) ((const char *     *) (value))
-#define NM_CAST_STRV_CC(value) ((const char *const*) (value))
-#endif
-
-#if _NM_CC_SUPPORT_GENERIC
-#define NM_PROPAGATE_CONST(test_expr, ptr) \
-	(_Generic ((test_expr), \
-	           const typeof (*(test_expr)) *: ((const typeof (*(ptr)) *) (ptr)), \
-	                                 default: (_Generic ((test_expr), \
-	                                                     typeof (*(test_expr)) *: (ptr)))))
-#else
-#define NM_PROPAGATE_CONST(test_expr, ptr) (ptr)
-#endif
-
-/* with the way it is implemented, the caller may or may not pass a trailing
- * ',' and it will work. However, this makes the macro unsuitable for initializing
- * an array. */
-#define NM_MAKE_STRV(...) \
-	((const char *const[(sizeof (((const char *const[]) { __VA_ARGS__ })) / sizeof (const char *)) + 1]) { __VA_ARGS__ })
-
-/*****************************************************************************/
-
-#define _NM_IN_SET_EVAL_1( op, _x, y)           (_x == (y))
-#define _NM_IN_SET_EVAL_2( op, _x, y, ...)      (_x == (y)) op _NM_IN_SET_EVAL_1  (op, _x, __VA_ARGS__)
-#define _NM_IN_SET_EVAL_3( op, _x, y, ...)      (_x == (y)) op _NM_IN_SET_EVAL_2  (op, _x, __VA_ARGS__)
-#define _NM_IN_SET_EVAL_4( op, _x, y, ...)      (_x == (y)) op _NM_IN_SET_EVAL_3  (op, _x, __VA_ARGS__)
-#define _NM_IN_SET_EVAL_5( op, _x, y, ...)      (_x == (y)) op _NM_IN_SET_EVAL_4  (op, _x, __VA_ARGS__)
-#define _NM_IN_SET_EVAL_6( op, _x, y, ...)      (_x == (y)) op _NM_IN_SET_EVAL_5  (op, _x, __VA_ARGS__)
-#define _NM_IN_SET_EVAL_7( op, _x, y, ...)      (_x == (y)) op _NM_IN_SET_EVAL_6  (op, _x, __VA_ARGS__)
-#define _NM_IN_SET_EVAL_8( op, _x, y, ...)      (_x == (y)) op _NM_IN_SET_EVAL_7  (op, _x, __VA_ARGS__)
-#define _NM_IN_SET_EVAL_9( op, _x, y, ...)      (_x == (y)) op _NM_IN_SET_EVAL_8  (op, _x, __VA_ARGS__)
-#define _NM_IN_SET_EVAL_10(op, _x, y, ...)      (_x == (y)) op _NM_IN_SET_EVAL_9  (op, _x, __VA_ARGS__)
-#define _NM_IN_SET_EVAL_11(op, _x, y, ...)      (_x == (y)) op _NM_IN_SET_EVAL_10 (op, _x, __VA_ARGS__)
-#define _NM_IN_SET_EVAL_12(op, _x, y, ...)      (_x == (y)) op _NM_IN_SET_EVAL_11 (op, _x, __VA_ARGS__)
-#define _NM_IN_SET_EVAL_13(op, _x, y, ...)      (_x == (y)) op _NM_IN_SET_EVAL_12 (op, _x, __VA_ARGS__)
-#define _NM_IN_SET_EVAL_14(op, _x, y, ...)      (_x == (y)) op _NM_IN_SET_EVAL_13 (op, _x, __VA_ARGS__)
-#define _NM_IN_SET_EVAL_15(op, _x, y, ...)      (_x == (y)) op _NM_IN_SET_EVAL_14 (op, _x, __VA_ARGS__)
-#define _NM_IN_SET_EVAL_16(op, _x, y, ...)      (_x == (y)) op _NM_IN_SET_EVAL_15 (op, _x, __VA_ARGS__)
-
-#define _NM_IN_SET_EVAL_N2(op, _x, n, ...)      (_NM_IN_SET_EVAL_##n(op, _x, __VA_ARGS__))
-#define _NM_IN_SET_EVAL_N(op, type, x, n, ...)                      \
-    ({                                                              \
-        type _x = (x);                                              \
-                                                                    \
-        /* trigger a -Wenum-compare warning */                      \
-        nm_assert (TRUE || _x == (x));                              \
-                                                                    \
-        !!_NM_IN_SET_EVAL_N2(op, _x, n, __VA_ARGS__);               \
-    })
-
-#define _NM_IN_SET(op, type, x, ...)        _NM_IN_SET_EVAL_N(op, type, x, NM_NARG (__VA_ARGS__), __VA_ARGS__)
-
-/* Beware that this does short-circuit evaluation (use "||" instead of "|")
- * which has a possibly unexpected non-function-like behavior.
- * Use NM_IN_SET_SE if you need all arguments to be evaluated. */
-#define NM_IN_SET(x, ...)                   _NM_IN_SET(||, typeof (x), x, __VA_ARGS__)
-
-/* "SE" stands for "side-effect". Contrary to NM_IN_SET(), this does not do
- * short-circuit evaluation, which can make a difference if the arguments have
- * side-effects. */
-#define NM_IN_SET_SE(x, ...)                _NM_IN_SET(|,  typeof (x), x, __VA_ARGS__)
-
-/* the *_TYPED forms allow to explicitly select the type of "x". This is useful
- * if "x" doesn't support typeof (bitfields) or you want to gracefully convert
- * a type using automatic type conversion rules (but not forcing the conversion
- * with a cast). */
-#define NM_IN_SET_TYPED(type, x, ...)       _NM_IN_SET(||, type,       x, __VA_ARGS__)
-#define NM_IN_SET_SE_TYPED(type, x, ...)    _NM_IN_SET(|,  type,       x, __VA_ARGS__)
-
-/*****************************************************************************/
-
-static inline gboolean
-_NM_IN_STRSET_streq (const char *x, const char *s)
-{
-	return s && strcmp (x, s) == 0;
-}
-
-#define _NM_IN_STRSET_EVAL_1( op, _x, y)        _NM_IN_STRSET_streq (_x, y)
-#define _NM_IN_STRSET_EVAL_2( op, _x, y, ...)   _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_1  (op, _x, __VA_ARGS__)
-#define _NM_IN_STRSET_EVAL_3( op, _x, y, ...)   _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_2  (op, _x, __VA_ARGS__)
-#define _NM_IN_STRSET_EVAL_4( op, _x, y, ...)   _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_3  (op, _x, __VA_ARGS__)
-#define _NM_IN_STRSET_EVAL_5( op, _x, y, ...)   _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_4  (op, _x, __VA_ARGS__)
-#define _NM_IN_STRSET_EVAL_6( op, _x, y, ...)   _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_5  (op, _x, __VA_ARGS__)
-#define _NM_IN_STRSET_EVAL_7( op, _x, y, ...)   _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_6  (op, _x, __VA_ARGS__)
-#define _NM_IN_STRSET_EVAL_8( op, _x, y, ...)   _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_7  (op, _x, __VA_ARGS__)
-#define _NM_IN_STRSET_EVAL_9( op, _x, y, ...)   _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_8  (op, _x, __VA_ARGS__)
-#define _NM_IN_STRSET_EVAL_10(op, _x, y, ...)   _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_9  (op, _x, __VA_ARGS__)
-#define _NM_IN_STRSET_EVAL_11(op, _x, y, ...)   _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_10 (op, _x, __VA_ARGS__)
-#define _NM_IN_STRSET_EVAL_12(op, _x, y, ...)   _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_11 (op, _x, __VA_ARGS__)
-#define _NM_IN_STRSET_EVAL_13(op, _x, y, ...)   _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_12 (op, _x, __VA_ARGS__)
-#define _NM_IN_STRSET_EVAL_14(op, _x, y, ...)   _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_13 (op, _x, __VA_ARGS__)
-#define _NM_IN_STRSET_EVAL_15(op, _x, y, ...)   _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_14 (op, _x, __VA_ARGS__)
-#define _NM_IN_STRSET_EVAL_16(op, _x, y, ...)   _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_15 (op, _x, __VA_ARGS__)
-
-#define _NM_IN_STRSET_EVAL_N2(op, _x, n, ...)   (_NM_IN_STRSET_EVAL_##n(op, _x, __VA_ARGS__))
-#define _NM_IN_STRSET_EVAL_N(op, x, n, ...)                       \
-    ({                                                            \
-        const char *_x = (x);                                     \
-        (   ((_x == NULL) && _NM_IN_SET_EVAL_N2    (op, ((const char *) NULL), n, __VA_ARGS__)) \
-         || ((_x != NULL) && _NM_IN_STRSET_EVAL_N2 (op, _x,                    n, __VA_ARGS__)) \
-        ); \
-    })
-
-/* Beware that this does short-circuit evaluation (use "||" instead of "|")
- * which has a possibly unexpected non-function-like behavior.
- * Use NM_IN_STRSET_SE if you need all arguments to be evaluated. */
-#define NM_IN_STRSET(x, ...)               _NM_IN_STRSET_EVAL_N(||, x, NM_NARG (__VA_ARGS__), __VA_ARGS__)
-
-/* "SE" stands for "side-effect". Contrary to NM_IN_STRSET(), this does not do
- * short-circuit evaluation, which can make a difference if the arguments have
- * side-effects. */
-#define NM_IN_STRSET_SE(x, ...)            _NM_IN_STRSET_EVAL_N(|, x, NM_NARG (__VA_ARGS__), __VA_ARGS__)
-
-#define NM_STRCHAR_ALL(str, ch_iter, predicate) \
-	({ \
-		gboolean _val = TRUE; \
-		const char *_str = (str); \
-		\
-		if (_str) { \
-			for (;;) { \
-				const char ch_iter = _str[0]; \
-				\
-				if (ch_iter != '\0') { \
-					if (predicate) {\
-						_str++; \
-						continue; \
-					} \
-					_val = FALSE; \
-				} \
-				break; \
-			} \
-		} \
-		_val; \
-	})
-
-#define NM_STRCHAR_ANY(str, ch_iter, predicate) \
-	({ \
-		gboolean _val = FALSE; \
-		const char *_str = (str); \
-		\
-		if (_str) { \
-			for (;;) { \
-				const char ch_iter = _str[0]; \
-				\
-				if (ch_iter != '\0') { \
-					if (predicate) { \
-						; \
-					} else { \
-						_str++; \
-						continue; \
-					} \
-					_val = TRUE; \
-				} \
-				break; \
-			} \
-		} \
-		_val; \
-	})
-
-/*****************************************************************************/
-
-/* NM_CACHED_QUARK() returns the GQuark for @string, but caches
- * it in a static variable to speed up future lookups.
- *
- * @string must be a string literal.
- */
-#define NM_CACHED_QUARK(string) \
-	({ \
-		static GQuark _nm_cached_quark = 0; \
-		\
-		(G_LIKELY (_nm_cached_quark != 0) \
-			? _nm_cached_quark \
-			: (_nm_cached_quark = g_quark_from_static_string (""string""))); \
-	})
-
-/* NM_CACHED_QUARK_FCN() is essentially the same as G_DEFINE_QUARK
- * with two differences:
- * - @string must be a quoted string-literal
- * - @fcn must be the full function name, while G_DEFINE_QUARK() appends
- *   "_quark" to the function name.
- * Both properties of G_DEFINE_QUARK() are non favorable, because you can no
- * longer grep for string/fcn -- unless you are aware that you are searching
- * for G_DEFINE_QUARK() and omit quotes / append _quark(). With NM_CACHED_QUARK_FCN(),
- * ctags/cscope can locate the use of @fcn (though it doesn't recognize that
- * NM_CACHED_QUARK_FCN() defines it).
- */
-#define NM_CACHED_QUARK_FCN(string, fcn) \
-GQuark \
-fcn (void) \
-{ \
-	return NM_CACHED_QUARK (string); \
-}
-
-/*****************************************************************************/
-
-static inline gboolean
-nm_streq (const char *s1, const char *s2)
-{
-	return strcmp (s1, s2) == 0;
-}
-
-static inline gboolean
-nm_streq0 (const char *s1, const char *s2)
-{
-	return    (s1 == s2)
-	       || (s1 && s2 && strcmp (s1, s2) == 0);
-}
-
-#define NM_STR_HAS_PREFIX(str, prefix) \
-	(strncmp ((str), ""prefix"", NM_STRLEN (prefix)) == 0)
-
-#define NM_STR_HAS_SUFFIX(str, suffix) \
-	({ \
-		const char *_str = (str); \
-		gsize _l = strlen (_str); \
-		\
-		(   (_l >= NM_STRLEN (suffix)) \
-		 && (memcmp (&_str[_l - NM_STRLEN (suffix)], \
-		             ""suffix"", \
-		             NM_STRLEN (suffix)) == 0)); \
-	})
-
-/*****************************************************************************/
-
-static inline GString *
-nm_gstring_prepare (GString **l)
-{
-	if (*l)
-		g_string_set_size (*l, 0);
-	else
-		*l = g_string_sized_new (30);
-	return *l;
-}
-
-static inline GString *
-nm_gstring_add_space_delimiter (GString *str)
-{
-	if (str->len > 0)
-		g_string_append_c (str, ' ');
-	return str;
-}
-
-static inline const char *
-nm_str_not_empty (const char *str)
-{
-	return str && str[0] ? str : NULL;
-}
-
-static inline char *
-nm_strdup_not_empty (const char *str)
-{
-	return str && str[0] ? g_strdup (str) : NULL;
-}
-
-static inline char *
-nm_str_realloc (char *str)
-{
-	gs_free char *s = str;
-
-	/* Returns a new clone of @str and frees @str. The point is that @str
-	 * possibly points to a larger chunck of memory. We want to freshly allocate
-	 * a buffer.
-	 *
-	 * We could use realloc(), but that might not do anything or leave
-	 * @str in its memory pool for chunks of a different size (bad for
-	 * fragmentation).
-	 *
-	 * This is only useful when we want to keep the buffer around for a long
-	 * time and want to re-allocate a more optimal buffer. */
-
-	return g_strdup (s);
-}
-
-/*****************************************************************************/
-
-#define NM_PRINT_FMT_QUOTED(cond, prefix, str, suffix, str_else) \
-	(cond) ? (prefix) : "", \
-	(cond) ? (str) : (str_else), \
-	(cond) ? (suffix) : ""
-#define NM_PRINT_FMT_QUOTE_STRING(arg) NM_PRINT_FMT_QUOTED((arg), "\"", (arg), "\"", "(null)")
-
-/*****************************************************************************/
-
-/* glib/C provides the following kind of assertions:
- *   - assert() -- disable with NDEBUG
- *   - g_return_if_fail() -- disable with G_DISABLE_CHECKS
- *   - g_assert() -- disable with G_DISABLE_ASSERT
- * but they are all enabled by default and usually even production builds have
- * these kind of assertions enabled. It also means, that disabling assertions
- * is an untested configuration, and might have bugs.
- *
- * Add our own assertion macro nm_assert(), which is disabled by default and must
- * be explicitly enabled. They are useful for more expensive checks or checks that
- * depend less on runtime conditions (that is, are generally expected to be true). */
-
-#ifndef NM_MORE_ASSERTS
-#define NM_MORE_ASSERTS 0
-#endif
-
-#if NM_MORE_ASSERTS
-#define nm_assert(cond) G_STMT_START { g_assert (cond); } G_STMT_END
-#define nm_assert_se(cond) G_STMT_START { if (G_LIKELY (cond)) { ; } else { g_assert (FALSE && (cond)); } } G_STMT_END
-#define nm_assert_not_reached() G_STMT_START { g_assert_not_reached (); } G_STMT_END
-#else
-#define nm_assert(cond) G_STMT_START { if (FALSE) { if (cond) { } } } G_STMT_END
-#define nm_assert_se(cond) G_STMT_START { if (G_LIKELY (cond)) { ; } } G_STMT_END
-#define nm_assert_not_reached() G_STMT_START { ; } G_STMT_END
-#endif
-
-/*****************************************************************************/
-
-#define NM_GOBJECT_PROPERTIES_DEFINE_BASE(...) \
-typedef enum { \
-	PROP_0, \
-	__VA_ARGS__ \
-	_PROPERTY_ENUMS_LAST, \
-} _PropertyEnums; \
-static GParamSpec *obj_properties[_PROPERTY_ENUMS_LAST] = { NULL, }
-
-#define NM_GOBJECT_PROPERTIES_DEFINE(obj_type, ...) \
-NM_GOBJECT_PROPERTIES_DEFINE_BASE (__VA_ARGS__); \
-static inline void \
-_nm_gobject_notify_together_impl (obj_type *obj, guint n, const _PropertyEnums *props) \
-{ \
-	const gboolean freeze_thaw = (n > 1); \
-	\
-	nm_assert (G_IS_OBJECT (obj)); \
-	nm_assert (n > 0); \
-	\
-	if (freeze_thaw) \
-		g_object_freeze_notify ((GObject *) obj); \
-	while (n-- > 0) { \
-		const _PropertyEnums prop = *props++; \
-		\
-		if (prop != PROP_0) { \
-			nm_assert ((gsize) prop < G_N_ELEMENTS (obj_properties)); \
-			nm_assert (obj_properties[prop]); \
-			g_object_notify_by_pspec ((GObject *) obj, obj_properties[prop]); \
-		} \
-	} \
-	if (freeze_thaw) \
-		g_object_thaw_notify ((GObject *) obj); \
-} \
-\
-static inline void \
-_notify (obj_type *obj, _PropertyEnums prop) \
-{ \
-	_nm_gobject_notify_together_impl (obj, 1, &prop); \
-} \
-
-/* invokes _notify() for all arguments (of type _PropertyEnums). Note, that if
- * there are more than one prop arguments, this will involve a freeze/thaw
- * of GObject property notifications. */
-#define nm_gobject_notify_together(obj, ...) \
-	_nm_gobject_notify_together_impl (obj, NM_NARG (__VA_ARGS__), (const _PropertyEnums[]) { __VA_ARGS__ })
-
-/*****************************************************************************/
-
-#define _NM_GET_PRIVATE(self, type, is_check, ...) (&(NM_GOBJECT_CAST_NON_NULL (type, (self), is_check, ##__VA_ARGS__)->_priv))
-#if _NM_CC_SUPPORT_AUTO_TYPE
-#define _NM_GET_PRIVATE_PTR(self, type, is_check, ...) \
-	({ \
-		_nm_auto_type _self = NM_GOBJECT_CAST_NON_NULL (type, (self), is_check, ##__VA_ARGS__); \
-		\
-		NM_PROPAGATE_CONST (_self, _self->_priv); \
-	})
-#else
-#define _NM_GET_PRIVATE_PTR(self, type, is_check, ...) (NM_GOBJECT_CAST_NON_NULL (type, (self), is_check, ##__VA_ARGS__)->_priv)
-#endif
-
-/*****************************************************************************/
-
-static inline gpointer
-nm_g_object_ref (gpointer obj)
-{
-	/* g_object_ref() doesn't accept NULL. */
-	if (obj)
-		g_object_ref (obj);
-	return obj;
-}
-#define nm_g_object_ref(obj) ((typeof (obj)) nm_g_object_ref (obj))
-
-static inline void
-nm_g_object_unref (gpointer obj)
-{
-	/* g_object_unref() doesn't accept NULL. Usully, we workaround that
-	 * by using g_clear_object(), but sometimes that is not convenient
-	 * (for example as as destroy function for a hash table that can contain
-	 * NULL values). */
-	if (obj)
-		g_object_unref (obj);
-}
-
-/* Assigns GObject @obj to destination @pp, and takes an additional ref.
- * The previous value of @pp is unrefed.
- *
- * It makes sure to first increase the ref-count of @obj, and handles %NULL
- * @obj correctly.
- * */
-#define nm_g_object_ref_set(pp, obj) \
-	({ \
-		typeof (*(pp)) *const _pp = (pp); \
-		typeof (*_pp) const _obj = (obj); \
-		typeof (*_pp) _p; \
-		gboolean _changed = FALSE; \
-		\
-		nm_assert (!_pp || !*_pp || G_IS_OBJECT (*_pp)); \
-		nm_assert (!_obj || G_IS_OBJECT (_obj)); \
-		\
-		if (   _pp \
-		    && ((_p = *_pp) != _obj)) { \
-			nm_g_object_ref (_obj); \
-			*_pp = _obj; \
-			nm_g_object_unref (_p); \
-			_changed = TRUE; \
-		} \
-		_changed; \
-	})
-
-#define nm_clear_pointer(pp, destroy) \
-	({ \
-		typeof (*(pp)) *_pp = (pp); \
-		typeof (*_pp) _p; \
-		gboolean _changed = FALSE; \
-		\
-		if (   _pp \
-		    && (_p = *_pp)) { \
-			_nm_unused gconstpointer _p_check_is_pointer = _p; \
-			\
-			*_pp = NULL; \
-			/* g_clear_pointer() assigns @destroy first to a local variable, so that
-			 * you can call "g_clear_pointer (pp, (GDestroyNotify) destroy);" without
-			 * gcc emitting a warning. We don't do that, hence, you cannot cast
-			 * "destroy" first.
-			 *
-			 * On the upside: you are not supposed to cast fcn, because the pointer
-			 * types are preserved. If you really need a cast, you should cast @pp.
-			 * But that is hardly ever necessary. */ \
-			(destroy) (_p); \
-			\
-			_changed = TRUE; \
-		} \
-		_changed; \
-	})
-
-/* basically, replaces
- *   g_clear_pointer (&location, g_free)
- * with
- *   nm_clear_g_free (&location)
- *
- * Another advantage is that by using a macro and typeof(), it is more
- * typesafe and gives you for example a compiler warning when pp is a const
- * pointer or points to a const-pointer.
- */
-#define nm_clear_g_free(pp) \
-	nm_clear_pointer (pp, g_free)
-
-#define nm_clear_g_object(pp) \
-	nm_clear_pointer (pp, g_object_unref)
-
-static inline gboolean
-nm_clear_g_source (guint *id)
-{
-	guint v;
-
-	if (   id
-	    && (v = *id)) {
-		*id = 0;
-		g_source_remove (v);
-		return TRUE;
-	}
-	return FALSE;
-}
-
-static inline gboolean
-nm_clear_g_signal_handler (gpointer self, gulong *id)
-{
-	gulong v;
-
-	if (   id
-	    && (v = *id)) {
-		*id = 0;
-		g_signal_handler_disconnect (self, v);
-		return TRUE;
-	}
-	return FALSE;
-}
-
-static inline gboolean
-nm_clear_g_variant (GVariant **variant)
-{
-	GVariant *v;
-
-	if (   variant
-	    && (v = *variant)) {
-		*variant = NULL;
-		g_variant_unref (v);
-		return TRUE;
-	}
-	return FALSE;
-}
-
-static inline gboolean
-nm_clear_g_cancellable (GCancellable **cancellable)
-{
-	GCancellable *v;
-
-	if (   cancellable
-	    && (v = *cancellable)) {
-		*cancellable = NULL;
-		g_cancellable_cancel (v);
-		g_object_unref (v);
-		return TRUE;
-	}
-	return FALSE;
-}
-
-/* If @cancellable_id is not 0, clear it and call g_cancellable_disconnect().
- * @cancellable may be %NULL, if there is nothing to disconnect.
- *
- * It's like nm_clear_g_signal_handler(), except that it uses g_cancellable_disconnect()
- * instead of g_signal_handler_disconnect().
- *
- * Note the warning in glib documentation about dead-lock and what g_cancellable_disconnect()
- * actually does. */
-static inline gboolean
-nm_clear_g_cancellable_disconnect (GCancellable *cancellable, gulong *cancellable_id)
-{
-	gulong id;
-
-	if (   cancellable_id
-	    && (id = *cancellable_id) != 0) {
-		*cancellable_id = 0;
-		g_cancellable_disconnect (cancellable, id);
-		return TRUE;
-	}
-	return FALSE;
-}
-
-/*****************************************************************************/
-
-static inline GVariant *
-nm_g_variant_ref (GVariant *v)
-{
-	if (v)
-		g_variant_ref (v);
-	return v;
-}
-
-static inline void
-nm_g_variant_unref (GVariant *v)
-{
-	if (v)
-		g_variant_unref (v);
-}
-
-/*****************************************************************************/
-
-/* Determine whether @x is a power of two (@x being an integer type).
- * Basically, this returns TRUE, if @x has exactly one bit set.
- * For negative values and zero, this always returns FALSE. */
-#define nm_utils_is_power_of_two(x) ({ \
-		typeof(x) __x = (x); \
-		\
-		(    (__x > ((typeof(__x)) 0)) \
-		 && ((__x & (__x - (((typeof(__x)) 1)))) == ((typeof(__x)) 0))); \
-	})
-
-#define NM_DIV_ROUND_UP(x, y) \
-	({ \
-		const typeof(x) _x = (x); \
-		const typeof(y) _y = (y); \
-		\
-		(_x / _y + !!(_x % _y)); \
-	})
-
-/*****************************************************************************/
-
-#define NM_UTILS_LOOKUP_DEFAULT(v)            return (v)
-#define NM_UTILS_LOOKUP_DEFAULT_WARN(v)       g_return_val_if_reached (v)
-#define NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT(v)  { nm_assert_not_reached (); return (v); }
-#define NM_UTILS_LOOKUP_ITEM(v, n)            (void) 0; case v: return (n); (void) 0
-#define NM_UTILS_LOOKUP_STR_ITEM(v, n)        NM_UTILS_LOOKUP_ITEM(v, ""n"")
-#define NM_UTILS_LOOKUP_ITEM_IGNORE(v)        (void) 0; case v: break; (void) 0
-#define NM_UTILS_LOOKUP_ITEM_IGNORE_OTHER()   (void) 0; default: break; (void) 0
-
-#define _NM_UTILS_LOOKUP_DEFINE(scope, fcn_name, lookup_type, result_type, unknown_val, ...) \
-scope result_type \
-fcn_name (lookup_type val) \
-{ \
-	switch (val) { \
-		(void) 0, \
-		__VA_ARGS__ \
-		(void) 0; \
-	}; \
-	{ unknown_val; } \
-}
-
-#define NM_UTILS_LOOKUP_STR_DEFINE(fcn_name, lookup_type, unknown_val, ...) \
-	_NM_UTILS_LOOKUP_DEFINE (, fcn_name, lookup_type, const char *, unknown_val, __VA_ARGS__)
-#define NM_UTILS_LOOKUP_STR_DEFINE_STATIC(fcn_name, lookup_type, unknown_val, ...) \
-	_NM_UTILS_LOOKUP_DEFINE (static, fcn_name, lookup_type, const char *, unknown_val, __VA_ARGS__)
-
-/* Call the string-lookup-table function @fcn_name. If the function returns
- * %NULL, the numeric index is converted to string using a alloca() buffer.
- * Beware: this macro uses alloca(). */
-#define NM_UTILS_LOOKUP_STR_A(fcn_name, idx) \
-	({ \
-		typeof (idx) _idx = (idx); \
-		const char *_s; \
-		\
-		_s = fcn_name (_idx); \
-		if (!_s) { \
-			_s = g_alloca (30); \
-			\
-			g_snprintf ((char *) _s, 30, "(%lld)", (long long) _idx); \
-		} \
-		_s; \
-	})
-
-/*****************************************************************************/
-
-/* check if @flags has exactly one flag (@check) set. You should call this
- * only with @check being a compile time constant and a power of two. */
-#define NM_FLAGS_HAS(flags, check)  \
-    ( G_STATIC_ASSERT_EXPR ((check) > 0 && ((check) & ((check) - 1)) == 0), NM_FLAGS_ANY ((flags), (check)) )
-
-#define NM_FLAGS_ANY(flags, check)  ( ( ((flags) & (check)) != 0       ) ? TRUE : FALSE )
-#define NM_FLAGS_ALL(flags, check)  ( ( ((flags) & (check)) == (check) ) ? TRUE : FALSE )
-
-#define NM_FLAGS_SET(flags, val)  ({ \
-		const typeof(flags) _flags = (flags); \
-		const typeof(flags) _val = (val); \
-		\
-		_flags | _val; \
-	})
-
-#define NM_FLAGS_UNSET(flags, val)  ({ \
-		const typeof(flags) _flags = (flags); \
-		const typeof(flags) _val = (val); \
-		\
-		_flags & (~_val); \
-	})
-
-#define NM_FLAGS_ASSIGN(flags, val, assign)  ({ \
-		const typeof(flags) _flags = (flags); \
-		const typeof(flags) _val = (val); \
-		\
-		(assign) \
-			? _flags | (_val) \
-			: _flags & (~_val); \
-	})
-
-/*****************************************************************************/
-
-#define _NM_BACKPORT_SYMBOL_IMPL(version, return_type, orig_func, versioned_func, args_typed, args) \
-return_type versioned_func args_typed; \
-_nm_externally_visible return_type versioned_func args_typed \
-{ \
-    return orig_func args; \
-} \
-return_type orig_func args_typed; \
-__asm__(".symver "G_STRINGIFY(versioned_func)", "G_STRINGIFY(orig_func)"@"G_STRINGIFY(version))
-
-#define NM_BACKPORT_SYMBOL(version, return_type, func, args_typed, args) \
-_NM_BACKPORT_SYMBOL_IMPL(version, return_type, func, _##func##_##version, args_typed, args)
-
-/*****************************************************************************/
-
-#define nm_str_skip_leading_spaces(str) \
-	({ \
-		typeof (*(str)) *_str = (str); \
-		_nm_unused const char *_str_type_check = _str; \
-		\
-		if (_str) { \
-			while (g_ascii_isspace (_str[0])) \
-				_str++; \
-		} \
-		_str; \
-	})
-
-static inline char *
-nm_strstrip (char *str)
-{
-	/* g_strstrip doesn't like NULL. */
-	return str ? g_strstrip (str) : NULL;
-}
-
-static inline const char *
-nm_strstrip_avoid_copy (const char *str, char **str_free)
-{
-	gsize l;
-	char *s;
-
-	nm_assert (str_free && !*str_free);
-
-	if (!str)
-		return NULL;
-
-	str = nm_str_skip_leading_spaces (str);
-	l = strlen (str);
-	if (   l == 0
-	    || !g_ascii_isspace (str[l - 1]))
-		return str;
-	while (   l > 0
-	       && g_ascii_isspace (str[l - 1]))
-		l--;
-
-	s = g_new (char, l + 1);
-	memcpy (s, str, l);
-	s[l] = '\0';
-	*str_free = s;
-	return s;
-}
-
-/* g_ptr_array_sort()'s compare function takes pointers to the
- * value. Thus, you cannot use strcmp directly. You can use
- * nm_strcmp_p().
- *
- * Like strcmp(), this function is not forgiving to accept %NULL. */
-static inline int
-nm_strcmp_p (gconstpointer a, gconstpointer b)
-{
-	const char *s1 = *((const char **) a);
-	const char *s2 = *((const char **) b);
-
-	return strcmp (s1, s2);
-}
-
-/*****************************************************************************/
-
-/* Taken from systemd's UNIQ_T and UNIQ macros. */
-
-#define NM_UNIQ_T(x, uniq) G_PASTE(__unique_prefix_, G_PASTE(x, uniq))
-#define NM_UNIQ __COUNTER__
-
-/*****************************************************************************/
-
-/* glib's MIN()/MAX() macros don't have function-like behavior, in that they evaluate
- * the argument possibly twice.
- *
- * Taken from systemd's MIN()/MAX() macros. */
-
-#define NM_MIN(a, b) __NM_MIN(NM_UNIQ, a, NM_UNIQ, b)
-#define __NM_MIN(aq, a, bq, b) \
-	({ \
-		typeof (a) NM_UNIQ_T(A, aq) = (a); \
-		typeof (b) NM_UNIQ_T(B, bq) = (b); \
-		((NM_UNIQ_T(A, aq) < NM_UNIQ_T(B, bq)) ? NM_UNIQ_T(A, aq) : NM_UNIQ_T(B, bq)); \
-	})
-
-#define NM_MAX(a, b) __NM_MAX(NM_UNIQ, a, NM_UNIQ, b)
-#define __NM_MAX(aq, a, bq, b) \
-	({ \
-		typeof (a) NM_UNIQ_T(A, aq) = (a); \
-		typeof (b) NM_UNIQ_T(B, bq) = (b); \
-		((NM_UNIQ_T(A, aq) > NM_UNIQ_T(B, bq)) ? NM_UNIQ_T(A, aq) : NM_UNIQ_T(B, bq)); \
-	})
-
-#define NM_CLAMP(x, low, high) __NM_CLAMP(NM_UNIQ, x, NM_UNIQ, low, NM_UNIQ, high)
-#define __NM_CLAMP(xq, x, lowq, low, highq, high) \
-	({ \
-		typeof(x)NM_UNIQ_T(X,xq) = (x); \
-		typeof(low) NM_UNIQ_T(LOW,lowq) = (low); \
-		typeof(high) NM_UNIQ_T(HIGH,highq) = (high); \
-		\
-		( (NM_UNIQ_T(X,xq) > NM_UNIQ_T(HIGH,highq)) \
-		  ? NM_UNIQ_T(HIGH,highq) \
-		  : (NM_UNIQ_T(X,xq) < NM_UNIQ_T(LOW,lowq)) \
-		     ? NM_UNIQ_T(LOW,lowq) \
-		     : NM_UNIQ_T(X,xq)); \
-	})
-
-#define NM_MAX_WITH_CMP(cmp, a, b) \
-	({ \
-		typeof (a) _a = (a); \
-		typeof (b) _b = (b); \
-		\
-		(  ((cmp (_a, _b)) >= 0) \
-		 ? _a \
-		 : _b); \
-	})
-
-/* evaluates to (void) if _A or _B are not constant or of different types */
-#define NM_CONST_MAX(_A, _B) \
-	(__builtin_choose_expr ((   __builtin_constant_p (_A) \
-	                         && __builtin_constant_p (_B) \
-	                         && __builtin_types_compatible_p (typeof (_A), typeof (_B))), \
-	                        ((_A) > (_B)) ? (_A) : (_B),                            \
-	                        ((void)  0)))
-
-/*****************************************************************************/
-
-static inline guint
-nm_encode_version (guint major, guint minor, guint micro)
-{
-	/* analog to the preprocessor macro NM_ENCODE_VERSION(). */
-	return (major << 16) | (minor << 8) | micro;
-}
-
-static inline void
-nm_decode_version (guint version, guint *major, guint *minor, guint *micro)
-{
-	*major = (version & 0xFFFF0000u) >> 16;
-	*minor = (version & 0x0000FF00u) >>  8;
-	*micro = (version & 0x000000FFu);
-}
-
-/*****************************************************************************/
-
-/* taken from systemd's DECIMAL_STR_MAX()
- *
- * Returns the number of chars needed to format variables of the
- * specified type as a decimal string. Adds in extra space for a
- * negative '-' prefix (hence works correctly on signed
- * types). Includes space for the trailing NUL. */
-#define NM_DECIMAL_STR_MAX(type) \
-    (2+(sizeof(type) <= 1 ? 3 : \
-        sizeof(type) <= 2 ? 5 : \
-        sizeof(type) <= 4 ? 10 : \
-        sizeof(type) <= 8 ? 20 : sizeof(int[-2*(sizeof(type) > 8)])))
-
-/*****************************************************************************/
-
-/* if @str is NULL, return "(null)". Otherwise, allocate a buffer using
- * alloca() of and fill it with @str. @str will be quoted with double quote.
- * If @str is longer then @trunc_at, the string is truncated and the closing
- * quote is instead '^' to indicate truncation.
- *
- * Thus, the maximum stack allocated buffer will be @trunc_at+3. The maximum
- * buffer size must be a constant and not larger than 300. */
-#define nm_strquote_a(trunc_at, str) \
-	({ \
-		const char *const _str = (str); \
-		\
-		(_str \
-			? ({ \
-				const gsize _trunc_at = (trunc_at); \
-				const gsize _strlen_trunc = NM_MIN (strlen (_str), _trunc_at); \
-				char *_buf; \
-				\
-				G_STATIC_ASSERT_EXPR ((trunc_at) <= 300); \
-				\
-				_buf = g_alloca (_strlen_trunc + 3); \
-				_buf[0] = '"'; \
-				memcpy (&_buf[1], _str, _strlen_trunc); \
-				_buf[_strlen_trunc + 1] = _str[_strlen_trunc] ? '^' : '"'; \
-				_buf[_strlen_trunc + 2] = '\0'; \
-				_buf; \
-			}) \
-			: "(null)"); \
-	})
-
-#define nm_sprintf_buf(buf, format, ...) \
-	({ \
-		char * _buf = (buf); \
-		int _buf_len; \
-		\
-		/* some static assert trying to ensure that the buffer is statically allocated.
-		 * It disallows a buffer size of sizeof(gpointer) to catch that. */ \
-		G_STATIC_ASSERT (G_N_ELEMENTS (buf) == sizeof (buf) && sizeof (buf) != sizeof (char *)); \
-		_buf_len = g_snprintf (_buf, sizeof (buf), \
-		                       ""format"", ##__VA_ARGS__); \
-		nm_assert (_buf_len < sizeof (buf)); \
-		_buf; \
-	})
-
-/* it is "unsafe" because @bufsize must not be a constant expression and
- * there is no check at compiletime. Regardless of that, the buffer size
- * must not be larger than 300 bytes, as this gets stack allocated. */
-#define nm_sprintf_buf_unsafe_a(bufsize, format, ...) \
-	({ \
-		char *_buf; \
-		int _buf_len; \
-		typeof (bufsize) _bufsize = (bufsize); \
-		\
-		nm_assert (_bufsize <= 300); \
-		\
-		_buf = g_alloca (_bufsize); \
-		_buf_len = g_snprintf (_buf, _bufsize, \
-		                       ""format"", ##__VA_ARGS__); \
-		nm_assert (_buf_len >= 0 && _buf_len < _bufsize); \
-		_buf; \
-	})
-
-#define nm_sprintf_bufa(bufsize, format, ...) \
-	({ \
-		G_STATIC_ASSERT_EXPR ((bufsize) <= 300); \
-		nm_sprintf_buf_unsafe_a ((bufsize), format, ##__VA_ARGS__); \
-	})
-
-/* aims to alloca() a buffer and fill it with printf(format, name).
- * Note that format must not contain any format specifier except
- * "%s".
- * If the resulting string would be too large for stack allocation,
- * it allocates a buffer with g_malloc() and assigns it to *p_val_to_free. */
-#define nm_construct_name_a(format, name, p_val_to_free) \
-	({ \
-		const char *const _name = (name); \
-		char **const _p_val_to_free = (p_val_to_free); \
-		const gsize _name_len = strlen (_name); \
-		char *_buf2; \
-		\
-		nm_assert (_p_val_to_free && !*_p_val_to_free); \
-		if (   NM_STRLEN (format) <= 290 \
-		    && _name_len < (gsize) (290 - NM_STRLEN (format))) \
-			_buf2 = nm_sprintf_buf_unsafe_a (NM_STRLEN (format) + _name_len, format, _name); \
-		else { \
-			_buf2 = g_strdup_printf (format, _name); \
-			*_p_val_to_free = _buf2; \
-		} \
-		(const char *) _buf2; \
-	})
-
-/*****************************************************************************/
-
-/**
- * The boolean type _Bool is C99 while we mostly stick to C89. However, _Bool is too
- * convenient to miss and is effectively available in gcc and clang. So, just use it.
- *
- * Usually, one would include "stdbool.h" to get the "bool" define which aliases
- * _Bool. We provide this define here, because we want to make use of it anywhere.
- * (also, stdbool.h is again C99).
- *
- * Using _Bool has advantages over gboolean:
- *
- * - commonly _Bool is one byte large, instead of gboolean's 4 bytes (because gboolean
- *   is a typedef for int). Especially when having boolean fields in a struct, we can
- *   thereby easily save some space.
- *
- * - _Bool type guarantees that two "true" expressions compare equal. E.g. the following
- *   will not work:
- *        gboolean v1 = 1;
- *        gboolean v2 = 2;
- *        g_assert_cmpint (v1, ==, v2); // will fail
- *   For that, we often to use !! to coerce gboolean values to 0 or 1:
- *        g_assert_cmpint (!!v2, ==, TRUE);
- *   With _Bool type, this will be handled properly by the compiler.
- *
- * - For structs, we might want to safe even more space and use bitfields:
- *       struct s1 {
- *           gboolean v1:1;
- *       };
- *   But the problem here is that gboolean is signed, so that
- *   v1 will be either 0 or -1 (not 1, TRUE). Thus, the following
- *   fails:
- *      struct s1 s = { .v1 = TRUE, };
- *      g_assert_cmpint (s1.v1, ==, TRUE);
- *   It will however work just fine with bool/_Bool while retaining the
- *   notion of having a boolean value.
- *
- * Also, add the defines for "true" and "false". Those are nicely highlighted by the editor
- * as special types, contrary to glib's "TRUE"/"FALSE".
- */
-
-#ifndef bool
-#define bool _Bool
-#define true    1
-#define false   0
-#endif
-
-#ifdef _G_BOOLEAN_EXPR
-/* g_assert() uses G_LIKELY(), which in turn uses _G_BOOLEAN_EXPR().
- * As glib's implementation uses a local variable _g_boolean_var_,
- * we cannot do
- *   g_assert (some_macro ());
- * where some_macro() itself expands to ({g_assert(); ...}).
- * In other words, you cannot have a g_assert() inside a g_assert()
- * without getting a -Werror=shadow failure.
- *
- * Workaround that by re-defining _G_BOOLEAN_EXPR()
- **/
-#undef  _G_BOOLEAN_EXPR
-#define __NM_G_BOOLEAN_EXPR_IMPL(v, expr) \
-	({ \
-		int NM_UNIQ_T(V, v); \
-		\
-		if (expr) \
-			NM_UNIQ_T(V, v) = 1; \
-		else \
-			NM_UNIQ_T(V, v) = 0; \
-		NM_UNIQ_T(V, v); \
-	})
-#define _G_BOOLEAN_EXPR(expr) __NM_G_BOOLEAN_EXPR_IMPL (NM_UNIQ, expr)
-#endif
-
-/*****************************************************************************/
-
-/**
- * nm_steal_int:
- * @p_val: pointer to an int type.
- *
- * Returns: *p_val and sets *p_val to zero the same time.
- *   Accepts %NULL, in which case also numeric 0 will be returned.
- */
-#define nm_steal_int(p_val) \
-	({ \
-		typeof (p_val) const _p_val = (p_val); \
-		typeof (*_p_val) _val = 0; \
-		\
-		if (   _p_val \
-		    && (_val = *_p_val)) { \
-			*_p_val = 0; \
-		} \
-		_val; \
-	})
-
-static inline int
-nm_steal_fd (int *p_fd)
-{
-	int fd;
-
-	if (   p_fd
-	    && ((fd = *p_fd) >= 0)) {
-		*p_fd = -1;
-		return fd;
-	}
-	return -1;
-}
-
-/**
- * nm_close:
- *
- * Like close() but throws an assertion if the input fd is
- * invalid.  Closing an invalid fd is a programming error, so
- * it's better to catch it early.
- */
-static inline int
-nm_close (int fd)
-{
-	int r;
-
-	r = close (fd);
-	nm_assert (r != -1 || fd < 0 || errno != EBADF);
-	return r;
-}
-
-#define NM_PID_T_INVAL ((pid_t) -1)
-
-#endif /* __NM_MACROS_INTERNAL_H__ */
diff --git a/shared/nm-utils/nm-obj.h b/shared/nm-utils/nm-obj.h
deleted file mode 100644
index 4edd1f3e..00000000
--- a/shared/nm-utils/nm-obj.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-/* NetworkManager -- Network link manager
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA.
- *
- * (C) Copyright 2017 Red Hat, Inc.
- */
-
-#ifndef __NM_OBJ_H__
-#define __NM_OBJ_H__
-
-/*****************************************************************************/
-
-#define NM_OBJ_REF_COUNT_STACKINIT (G_MAXINT)
-
-typedef struct _NMObjBaseInst  NMObjBaseInst;
-typedef struct _NMObjBaseClass NMObjBaseClass;
-
-struct _NMObjBaseInst {
-	/* The first field of NMObjBaseInst is compatible with GObject.
-	 * Basically, NMObjBaseInst is an abstract base type of GTypeInstance.
-	 *
-	 * If you do it right, you may derive a type of NMObjBaseInst as a proper GTypeInstance.
-	 * That involves allocating a GType for it, which can be inconvenient because
-	 * a GType is dynamically created (and the class can no longer be immutable
-	 * memory).
-	 *
-	 * Even if your implementation of NMObjBaseInst is not a full fledged GType(Instance),
-	 * you still can use GTypeInstances in the same context as you can decide based on the
-	 * NMObjBaseClass with what kind of object you are dealing with.
-	 *
-	 * Basically, the only thing NMObjBaseInst gives you is access to an
-	 * NMObjBaseClass instance.
-	 */
-	union {
-		const NMObjBaseClass *klass;
-		GTypeInstance g_type_instance;
-	};
-};
-
-struct _NMObjBaseClass {
-	/* NMObjBaseClass is the base class of all NMObjBaseInst implementations.
-	 * Note that it is also an abstract super class of GTypeInstance, that means
-	 * you may implement a NMObjBaseClass as a subtype of GTypeClass.
-	 *
-	 * For that to work, you must properly set the GTypeClass instance (and its
-	 * GType).
-	 *
-	 * Note that to implement a NMObjBaseClass that is *not* a GTypeClass, you wouldn't
-	 * set the GType. Hence, this field is only useful for type implementations that actually
-	 * extend GTypeClass.
-	 *
-	 * In a way it is wrong that NMObjBaseClass has the GType member, because it is
-	 * a base class of GTypeClass and doesn't necessarily use the GType. However,
-	 * it is here so that G_TYPE_CHECK_INSTANCE_TYPE() and friends work correctly
-	 * on any NMObjectClass. That means, while not necessary, it is convenient that
-	 * a NMObjBaseClass has all members of GTypeClass.
-	 * Also note that usually you have only one instance of a certain type, so this
-	 * wastes just a few bytes for the unneeded GType.
-	 */
-	union {
-		GType g_type;
-		GTypeClass g_type_class;
-	};
-};
-
-/*****************************************************************************/
-
-#endif /* __NM_OBJ_H__ */
diff --git a/shared/nm-utils/nm-random-utils.c b/shared/nm-utils/nm-random-utils.c
deleted file mode 100644
index d7c7da42..00000000
--- a/shared/nm-utils/nm-random-utils.c
+++ /dev/null
@@ -1,165 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-/* NetworkManager -- Network link manager
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA.
- *
- * (C) Copyright 2017 Red Hat, Inc.
- */
-
-#include "nm-default.h"
-
-#include "nm-random-utils.h"
-
-#include <fcntl.h>
-
-#if USE_SYS_RANDOM_H
-#include <sys/random.h>
-#else
-#include <linux/random.h>
-#endif
-
-#include "nm-shared-utils.h"
-
-/*****************************************************************************/
-
-/**
- * nm_utils_random_bytes:
- * @p: the buffer to fill
- * @n: the number of bytes to write to @p.
- *
- * Uses getrandom() or reads /dev/urandom to fill the buffer
- * with random data. If all fails, as last fallback it uses
- * GRand to fill the buffer with pseudo random numbers.
- * The function always succeeds in writing some random numbers
- * to the buffer. The return value of FALSE indicates that the
- * obtained bytes are probably not of good randomness.
- *
- * Returns: whether the written bytes are good. If you
- * don't require good randomness, you can ignore the return
- * value.
- *
- * Note that if calling getrandom() fails because there is not enough
- * entropy (at early boot), the function will read /dev/urandom.
- * Which of course, still has low entropy, and cause kernel to log
- * a warning.
- */
-gboolean
-nm_utils_random_bytes (void *p, size_t n)
-{
-	int fd;
-	int r;
-	gboolean has_high_quality = TRUE;
-	gboolean urandom_success;
-	guint8 *buf = p;
-	gboolean avoid_urandom = FALSE;
-
-	g_return_val_if_fail (p, FALSE);
-	g_return_val_if_fail (n > 0, FALSE);
-
-#if HAVE_GETRANDOM
-	{
-		static gboolean have_syscall = TRUE;
-
-		if (have_syscall) {
-			r = getrandom (buf, n, GRND_NONBLOCK);
-			if (r > 0) {
-				if ((size_t) r == n)
-					return TRUE;
-
-				/* no or partial read. There is not enough entropy.
-				 * Fill the rest reading from urandom, and remember that
-				 * some bits are not high quality. */
-				nm_assert (r < n);
-				buf += r;
-				n -= r;
-				has_high_quality = FALSE;
-
-				/* At this point, we don't want to read /dev/urandom, because
-				 * the entropy pool is low (early boot?), and asking for more
-				 * entropy causes kernel messages to be logged.
-				 *
-				 * We use our fallback via GRand. Note that g_rand_new() also
-				 * tries to seed itself with data from /dev/urandom, but since
-				 * we reuse the instance, it shouldn't matter. */
-				avoid_urandom = TRUE;
-			} else {
-				if (errno == ENOSYS) {
-					/* no support for getrandom(). We don't know whether
-					 * we urandom will give us good quality. Assume yes. */
-					have_syscall = FALSE;
-				} else {
-					/* unknown error. We'll read urandom below, but we don't have
-					 * high-quality randomness. */
-					has_high_quality = FALSE;
-				}
-			}
-		}
-	}
-#endif
-
-	urandom_success = FALSE;
-	if (!avoid_urandom) {
-fd_open:
-		fd = open ("/dev/urandom", O_RDONLY | O_CLOEXEC | O_NOCTTY);
-		if (fd < 0) {
-			r = errno;
-			if (r == EINTR)
-				goto fd_open;
-		} else {
-			r = nm_utils_fd_read_loop_exact (fd, buf, n, TRUE);
-			nm_close (fd);
-			if (r >= 0)
-				urandom_success = TRUE;
-		}
-	}
-
-	if (!urandom_success) {
-		static _nm_thread_local GRand *rand = NULL;
-		gsize i;
-		int j;
-
-		/* we failed to fill the bytes reading from urandom.
-		 * Fill the bits using GRand pseudo random numbers.
-		 *
-		 * We don't have good quality.
-		 */
-		has_high_quality = FALSE;
-
-		if (G_UNLIKELY (!rand))
-			rand = g_rand_new ();
-
-		nm_assert (n > 0);
-		i = 0;
-		for (;;) {
-			const union {
-				guint32 v32;
-				guint8 v8[4];
-			} v = {
-				.v32 = g_rand_int (rand),
-			};
-
-			for (j = 0; j < 4; ) {
-				buf[i++] = v.v8[j++];
-				if (i >= n)
-					goto done;
-			}
-		}
-done:
-		;
-	}
-
-	return has_high_quality;
-}
diff --git a/shared/nm-utils/nm-random-utils.h b/shared/nm-utils/nm-random-utils.h
deleted file mode 100644
index 15a118d3..00000000
--- a/shared/nm-utils/nm-random-utils.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-/* NetworkManager -- Network link manager
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA.
- *
- * (C) Copyright 2017 Red Hat, Inc.
- */
-
-#ifndef __NM_RANDOM_UTILS_H__
-#define __NM_RANDOM_UTILS_H__
-
-gboolean nm_utils_random_bytes (void *p, size_t n);
-
-#endif /* __NM_RANDOM_UTILS_H__ */
diff --git a/shared/nm-utils/nm-secret-utils.c b/shared/nm-utils/nm-secret-utils.c
deleted file mode 100644
index ec5cc6b1..00000000
--- a/shared/nm-utils/nm-secret-utils.c
+++ /dev/null
@@ -1,161 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-/* NetworkManager -- Network link manager
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA.
- *
- * (C) Copyright 2018 Red Hat, Inc.
- * (C) Copyright 2015 - 2019 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
- */
-
-#include "nm-default.h"
-
-#include "nm-secret-utils.h"
-
-/*****************************************************************************/
-
-void
-nm_explicit_bzero (void *s, gsize n)
-{
-	/* gracefully handle n == 0. This is important, callers rely on it. */
-	if (n > 0) {
-		nm_assert (s);
-#if defined (HAVE_DECL_EXPLICIT_BZERO) && HAVE_DECL_EXPLICIT_BZERO
-		explicit_bzero (s, n);
-#else
-		/* don't bother with a workaround. Use a reasonable glibc. */
-		memset (s, 0, n);
-#endif
-	}
-}
-
-/*****************************************************************************/
-
-char *
-nm_secret_strchomp (char *secret)
-{
-	gsize len;
-
-	g_return_val_if_fail (secret, NULL);
-
-	/* it's actually identical to g_strchomp(). However,
-	 * the glib function does not document, that it clears the
-	 * memory. For @secret, we don't only want to truncate trailing
-	 * spaces, we want to overwrite them with NUL. */
-
-	len = strlen (secret);
-	while (len--) {
-		if (g_ascii_isspace ((guchar) secret[len]))
-			secret[len] = '\0';
-		else
-			break;
-	}
-
-	return secret;
-}
-
-/*****************************************************************************/
-
-GBytes *
-nm_secret_copy_to_gbytes (gconstpointer mem, gsize mem_len)
-{
-	NMSecretBuf *b;
-
-	if (mem_len == 0)
-		return g_bytes_new_static ("", 0);
-
-	nm_assert (mem);
-
-	/* NUL terminate the buffer.
-	 *
-	 * The entire buffer is already malloc'ed and likely has some room for padding.
-	 * Thus, in many situations, this additional byte will cause no overhead in
-	 * practice.
-	 *
-	 * Even if it causes an overhead, do it just for safety. Yes, the returned
-	 * bytes is not a NUL terminated string and no user must rely on this. Do
-	 * not treat binary data as NUL terminated strings, unless you know what
-	 * you are doing. Anyway, defensive FTW.
-	 */
-
-	b = nm_secret_buf_new (mem_len + 1);
-	memcpy (b->bin, mem, mem_len);
-	b->bin[mem_len] = 0;
-	return nm_secret_buf_to_gbytes_take (b, mem_len);
-}
-
-/*****************************************************************************/
-
-NMSecretBuf *
-nm_secret_buf_new (gsize len)
-{
-	NMSecretBuf *secret;
-
-	nm_assert (len > 0);
-
-	secret = g_malloc (sizeof (NMSecretBuf) + len);
-	*((gsize *) &(secret->len)) = len;
-	return secret;
-}
-
-static void
-_secret_buf_free (gpointer user_data)
-{
-	NMSecretBuf *secret = user_data;
-
-	nm_assert (secret);
-	nm_assert (secret->len > 0);
-
-	nm_explicit_bzero (secret->bin, secret->len);
-	g_free (user_data);
-}
-
-GBytes *
-nm_secret_buf_to_gbytes_take (NMSecretBuf *secret, gssize actual_len)
-{
-	nm_assert (secret);
-	nm_assert (secret->len > 0);
-	nm_assert (actual_len == -1 || (actual_len >= 0 && actual_len <= secret->len));
-	return g_bytes_new_with_free_func (secret->bin,
-	                                   actual_len >= 0 ? (gsize) actual_len : secret->len,
-	                                   _secret_buf_free,
-	                                   secret);
-}
-
-/*****************************************************************************/
-
-/**
- * nm_utils_memeqzero_secret:
- * @data: the data pointer to check (may be %NULL if @length is zero).
- * @length: the number of bytes to check.
- *
- * Checks that all bytes are zero. This always takes the same amount
- * of time to prevent timing attacks.
- *
- * Returns: whether all bytes are zero.
- */
-gboolean
-nm_utils_memeqzero_secret (gconstpointer data, gsize length)
-{
-	const guint8 *const key = data;
-	volatile guint8 acc = 0;
-	gsize i;
-
-	for (i = 0; i < length; i++) {
-		acc |= key[i];
-		asm volatile("" : "=r"(acc) : "0"(acc));
-	}
-	return 1 & ((acc - 1) >> 8);
-}
diff --git a/shared/nm-utils/nm-secret-utils.h b/shared/nm-utils/nm-secret-utils.h
deleted file mode 100644
index 034ef7bd..00000000
--- a/shared/nm-utils/nm-secret-utils.h
+++ /dev/null
@@ -1,178 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-/* NetworkManager -- Network link manager
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA.
- *
- * (C) Copyright 2018 Red Hat, Inc.
- */
-
-#ifndef __NM_SECRET_UTILS_H__
-#define __NM_SECRET_UTILS_H__
-
-#include "nm-macros-internal.h"
-
-/*****************************************************************************/
-
-void nm_explicit_bzero (void *s, gsize n);
-
-/*****************************************************************************/
-
-char *nm_secret_strchomp (char *secret);
-
-/*****************************************************************************/
-
-static inline void
-nm_free_secret (char *secret)
-{
-	if (secret) {
-		nm_explicit_bzero (secret, strlen (secret));
-		g_free (secret);
-	}
-}
-
-NM_AUTO_DEFINE_FCN0 (char *, _nm_auto_free_secret, nm_free_secret)
-/**
- * nm_auto_free_secret:
- *
- * Call g_free() on a variable location when it goes out of scope.
- * Also, previously, calls memset(loc, 0, strlen(loc)) to clear out
- * the secret.
- */
-#define nm_auto_free_secret nm_auto(_nm_auto_free_secret)
-
-/*****************************************************************************/
-
-GBytes *nm_secret_copy_to_gbytes (gconstpointer mem, gsize mem_len);
-
-/*****************************************************************************/
-
-/* NMSecretPtr is a pair of malloc'ed data pointer and the length of the
- * data. The purpose is to use it in combination with nm_auto_clear_secret_ptr
- * which ensures that the data pointer (with all len bytes) is cleared upon
- * cleanup. */
-typedef struct {
-	gsize len;
-
-	/* the data pointer. This pointer must be allocated with malloc (at least
-	 * when used with nm_secret_ptr_clear()). */
-	union {
-		char *str;
-		void *ptr;
-		guint8 *bin;
-	};
-} NMSecretPtr;
-
-static inline void
-nm_secret_ptr_bzero (NMSecretPtr *secret)
-{
-	if (secret) {
-		if (secret->len > 0) {
-			if (secret->ptr)
-				nm_explicit_bzero (secret->ptr, secret->len);
-		}
-	}
-}
-
-#define nm_auto_bzero_secret_ptr nm_auto(nm_secret_ptr_bzero)
-
-static inline void
-nm_secret_ptr_clear (NMSecretPtr *secret)
-{
-	if (secret) {
-		if (secret->len > 0) {
-			if (secret->ptr)
-				nm_explicit_bzero (secret->ptr, secret->len);
-			secret->len = 0;
-		}
-		nm_clear_g_free (&secret->ptr);
-	}
-}
-
-#define nm_auto_clear_secret_ptr nm_auto(nm_secret_ptr_clear)
-
-#define NM_SECRET_PTR_INIT() \
-	((const NMSecretPtr) { \
-		.len = 0, \
-		.ptr = NULL, \
-	})
-
-#define NM_SECRET_PTR_STATIC(_len) \
-	((const NMSecretPtr) { \
-		.len = _len, \
-		.ptr = ((guint8 [_len]) { }), \
-	})
-
-#define NM_SECRET_PTR_ARRAY(_arr) \
-	((const NMSecretPtr) { \
-		.len = G_N_ELEMENTS (_arr) * sizeof ((_arr)[0]), \
-		.ptr = &((_arr)[0]), \
-	})
-
-static inline void
-nm_secret_ptr_clear_static (const NMSecretPtr *secret)
-{
-	if (secret) {
-		if (secret->len > 0) {
-			nm_assert (secret->ptr);
-			nm_explicit_bzero (secret->ptr, secret->len);
-		}
-	}
-}
-
-#define nm_auto_clear_static_secret_ptr nm_auto(nm_secret_ptr_clear_static)
-
-static inline void
-nm_secret_ptr_move (NMSecretPtr *dst, NMSecretPtr *src)
-{
-	if (dst && dst != src) {
-		*dst = *src;
-		src->len = 0;
-		src->ptr = NULL;
-	}
-}
-
-/*****************************************************************************/
-
-typedef struct {
-	const gsize len;
-	union {
-		char str[0];
-		guint8 bin[0];
-	};
-} NMSecretBuf;
-
-static inline void
-_nm_auto_free_secret_buf (NMSecretBuf **ptr)
-{
-	NMSecretBuf *b = *ptr;
-
-	if (b) {
-		nm_assert (b->len > 0);
-		nm_explicit_bzero (b->bin, b->len);
-		g_free (b);
-	}
-}
-#define nm_auto_free_secret_buf nm_auto(_nm_auto_free_secret_buf)
-
-NMSecretBuf *nm_secret_buf_new (gsize len);
-
-GBytes *nm_secret_buf_to_gbytes_take (NMSecretBuf *secret, gssize actual_len);
-
-/*****************************************************************************/
-
-gboolean nm_utils_memeqzero_secret (gconstpointer data, gsize length);
-
-#endif /* __NM_SECRET_UTILS_H__ */
diff --git a/shared/nm-utils/nm-shared-utils.c b/shared/nm-utils/nm-shared-utils.c
deleted file mode 100644
index 6a43c670..00000000
--- a/shared/nm-utils/nm-shared-utils.c
+++ /dev/null
@@ -1,2741 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-/* NetworkManager -- Network link manager
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA.
- *
- * (C) Copyright 2016 Red Hat, Inc.
- */
-
-#include "nm-default.h"
-
-#include "nm-shared-utils.h"
-
-#include <arpa/inet.h>
-#include <poll.h>
-#include <fcntl.h>
-#include <sys/syscall.h>
-
-#include "nm-errno.h"
-
-/*****************************************************************************/
-
-const void *const _NM_PTRARRAY_EMPTY[1] = { NULL };
-
-/*****************************************************************************/
-
-const NMIPAddr nm_ip_addr_zero = { };
-
-/* this initializes a struct in_addr/in6_addr and allows for untrusted
- * arguments (like unsuitable @addr_family or @src_len). It's almost safe
- * in the sense that it verifies input arguments strictly. Also, it
- * uses memcpy() to access @src, so alignment is not an issue.
- *
- * Only potential pitfalls:
- *
- * - it allows for @addr_family to be AF_UNSPEC. If that is the case (and the
- *   caller allows for that), the caller MUST provide @out_addr_family.
- * - when setting @dst to an IPv4 address, the trailing bytes are not touched.
- *   Meaning, if @dst is an NMIPAddr union, only the first bytes will be set.
- *   If that matter to you, clear @dst before. */
-gboolean
-nm_ip_addr_set_from_untrusted (int addr_family,
-                               gpointer dst,
-                               gconstpointer src,
-                               gsize src_len,
-                               int *out_addr_family)
-{
-	nm_assert (dst);
-
-	switch (addr_family) {
-	case AF_UNSPEC:
-		if (!out_addr_family) {
-			/* when the callers allow undefined @addr_family, they must provide
-			 * an @out_addr_family argument. */
-			nm_assert_not_reached ();
-			return FALSE;
-		}
-		switch (src_len) {
-		case sizeof (struct in_addr):  addr_family = AF_INET;  break;
-		case sizeof (struct in6_addr): addr_family = AF_INET6; break;
-		default:
-			return FALSE;
-		}
-		break;
-	case AF_INET:
-		if (src_len != sizeof (struct in_addr))
-			return FALSE;
-		break;
-	case AF_INET6:
-		if (src_len != sizeof (struct in6_addr))
-			return FALSE;
-		break;
-	default:
-		/* when the callers allow undefined @addr_family, they must provide
-		 * an @out_addr_family argument. */
-		nm_assert (out_addr_family);
-		return FALSE;
-	}
-
-	nm_assert (src);
-
-	memcpy (dst, src, src_len);
-	NM_SET_OUT (out_addr_family, addr_family);
-	return TRUE;
-}
-
-/*****************************************************************************/
-
-pid_t
-nm_utils_gettid (void)
-{
-	return (pid_t) syscall (SYS_gettid);
-}
-
-/* Used for asserting that this function is called on the main-thread.
- * The main-thread is determined by remembering the thread-id
- * of when the function was called the first time.
- *
- * When forking, the thread-id is again reset upon first call. */
-gboolean
-_nm_assert_on_main_thread (void)
-{
-	G_LOCK_DEFINE_STATIC (lock);
-	static pid_t seen_tid;
-	static pid_t seen_pid;
-	pid_t tid;
-	pid_t pid;
-	gboolean success = FALSE;
-
-	tid = nm_utils_gettid ();
-	nm_assert (tid != 0);
-
-	G_LOCK (lock);
-
-	if (G_LIKELY (tid == seen_tid)) {
-		/* we don't care about false positives (when the process forked, and the thread-id
-		 * is accidentally re-used) . It's for assertions only. */
-		success = TRUE;
-	} else {
-		pid = getpid ();
-		nm_assert (pid != 0);
-
-		if (   seen_tid == 0
-			|| seen_pid != pid) {
-			/* either this is the first time we call the function, or the process
-			 * forked. In both cases, remember the thread-id. */
-			seen_tid = tid;
-			seen_pid = pid;
-			success = TRUE;
-		}
-	}
-
-	G_UNLOCK (lock);
-
-	return success;
-}
-
-/*****************************************************************************/
-
-void
-nm_utils_strbuf_append_c (char **buf, gsize *len, char c)
-{
-	switch (*len) {
-	case 0:
-		return;
-	case 1:
-		(*buf)[0] = '\0';
-		*len = 0;
-		(*buf)++;
-		return;
-	default:
-		(*buf)[0] = c;
-		(*buf)[1] = '\0';
-		(*len)--;
-		(*buf)++;
-		return;
-	}
-}
-
-void
-nm_utils_strbuf_append_bin (char **buf, gsize *len, gconstpointer str, gsize str_len)
-{
-	switch (*len) {
-	case 0:
-		return;
-	case 1:
-		if (str_len == 0) {
-			(*buf)[0] = '\0';
-			return;
-		}
-		(*buf)[0] = '\0';
-		*len = 0;
-		(*buf)++;
-		return;
-	default:
-		if (str_len == 0) {
-			(*buf)[0] = '\0';
-			return;
-		}
-		if (str_len >= *len) {
-			memcpy (*buf, str, *len - 1);
-			(*buf)[*len - 1] = '\0';
-			*buf = &(*buf)[*len];
-			*len = 0;
-		} else {
-			memcpy (*buf, str, str_len);
-			*buf = &(*buf)[str_len];
-			(*buf)[0] = '\0';
-			*len -= str_len;
-		}
-		return;
-	}
-}
-
-void
-nm_utils_strbuf_append_str (char **buf, gsize *len, const char *str)
-{
-	gsize src_len;
-
-	switch (*len) {
-	case 0:
-		return;
-	case 1:
-		if (!str || !*str) {
-			(*buf)[0] = '\0';
-			return;
-		}
-		(*buf)[0] = '\0';
-		*len = 0;
-		(*buf)++;
-		return;
-	default:
-		if (!str || !*str) {
-			(*buf)[0] = '\0';
-			return;
-		}
-		src_len = g_strlcpy (*buf, str, *len);
-		if (src_len >= *len) {
-			*buf = &(*buf)[*len];
-			*len = 0;
-		} else {
-			*buf = &(*buf)[src_len];
-			*len -= src_len;
-		}
-		return;
-	}
-}
-
-void
-nm_utils_strbuf_append (char **buf, gsize *len, const char *format, ...)
-{
-	char *p = *buf;
-	va_list args;
-	int retval;
-
-	if (*len == 0)
-		return;
-
-	va_start (args, format);
-	retval = g_vsnprintf (p, *len, format, args);
-	va_end (args);
-
-	if ((gsize) retval >= *len) {
-		*buf = &p[*len];
-		*len = 0;
-	} else {
-		*buf = &p[retval];
-		*len -= retval;
-	}
-}
-
-/**
- * nm_utils_strbuf_seek_end:
- * @buf: the input/output buffer
- * @len: the input/output length of the buffer.
- *
- * Commonly, one uses nm_utils_strbuf_append*(), to incrementally
- * append strings to the buffer. However, sometimes we need to use
- * existing API to write to the buffer.
- * After doing so, we want to adjust the buffer counter.
- * Essentially,
- *
- *   g_snprintf (buf, len, ...);
- *   nm_utils_strbuf_seek_end (&buf, &len);
- *
- * is almost the same as
- *
- *   nm_utils_strbuf_append (&buf, &len, ...);
- *
- * The only difference is the behavior when the string got truncated:
- * nm_utils_strbuf_append() will recognize that and set the remaining
- * length to zero.
- *
- * In general, the behavior is:
- *
- *  - if *len is zero, do nothing
- *  - if the buffer contains a NUL byte within the first *len characters,
- *    the buffer is pointed to the NUL byte and len is adjusted. In this
- *    case, the remaining *len is always >= 1.
- *    In particular, that is also the case if the NUL byte is at the very last
- *    position ((*buf)[*len -1]). That happens, when the previous operation
- *    either fit the string exactly into the buffer or the string was truncated
- *    by g_snprintf(). The difference cannot be determined.
- *  - if the buffer contains no NUL bytes within the first *len characters,
- *    write NUL at the last position, set *len to zero, and point *buf past
- *    the NUL byte. This would happen with
- *
- *       strncpy (buf, long_str, len);
- *       nm_utils_strbuf_seek_end (&buf, &len).
- *
- *    where strncpy() does truncate the string and not NUL terminate it.
- *    nm_utils_strbuf_seek_end() would then NUL terminate it.
- */
-void
-nm_utils_strbuf_seek_end (char **buf, gsize *len)
-{
-	gsize l;
-	char *end;
-
-	nm_assert (len);
-	nm_assert (buf && *buf);
-
-	if (*len <= 1) {
-		if (   *len == 1
-		    && (*buf)[0])
-			goto truncate;
-		return;
-	}
-
-	end = memchr (*buf, 0, *len);
-	if (end) {
-		l = end - *buf;
-		nm_assert (l < *len);
-
-		*buf = end;
-		*len -= l;
-		return;
-	}
-
-truncate:
-	/* hm, no NUL character within len bytes.
-	 * Just NUL terminate the array and consume them
-	 * all. */
-	*buf += *len;
-	(*buf)[-1] = '\0';
-	*len = 0;
-	return;
-}
-
-/*****************************************************************************/
-
-/**
- * nm_utils_gbytes_equals:
- * @bytes: (allow-none): a #GBytes array to compare. Note that
- *   %NULL is treated like an #GBytes array of length zero.
- * @mem_data: the data pointer with @mem_len bytes
- * @mem_len: the length of the data pointer
- *
- * Returns: %TRUE if @bytes contains the same data as @mem_data. As a
- *   special case, a %NULL @bytes is treated like an empty array.
- */
-gboolean
-nm_utils_gbytes_equal_mem (GBytes *bytes,
-                           gconstpointer mem_data,
-                           gsize mem_len)
-{
-	gconstpointer p;
-	gsize l;
-
-	if (!bytes) {
-		/* as a special case, let %NULL GBytes compare idential
-		 * to an empty array. */
-		return (mem_len == 0);
-	}
-
-	p = g_bytes_get_data (bytes, &l);
-	return    l == mem_len
-	       && (   mem_len == 0 /* allow @mem_data to be %NULL */
-	           || memcmp (p, mem_data, mem_len) == 0);
-}
-
-GVariant *
-nm_utils_gbytes_to_variant_ay (GBytes *bytes)
-{
-	const guint8 *p;
-	gsize l;
-
-	if (!bytes) {
-		/* for convenience, accept NULL to return an empty variant */
-		return g_variant_new_array (G_VARIANT_TYPE_BYTE, NULL, 0);
-	}
-
-	p = g_bytes_get_data (bytes, &l);
-	return g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, p, l, 1);
-}
-
-/*****************************************************************************/
-
-/**
- * nm_strquote:
- * @buf: the output buffer of where to write the quoted @str argument.
- * @buf_len: the size of @buf.
- * @str: (allow-none): the string to quote.
- *
- * Writes @str to @buf with quoting. The resulting buffer
- * is always NUL terminated, unless @buf_len is zero.
- * If @str is %NULL, it writes "(null)".
- *
- * If @str needs to be truncated, the closing quote is '^' instead
- * of '"'.
- *
- * This is similar to nm_strquote_a(), which however uses alloca()
- * to allocate a new buffer. Also, here @buf_len is the size of @buf,
- * while nm_strquote_a() has the number of characters to print. The latter
- * doesn't include the quoting.
- *
- * Returns: the input buffer with the quoted string.
- */
-const char *
-nm_strquote (char *buf, gsize buf_len, const char *str)
-{
-	const char *const buf0 = buf;
-
-	if (!str) {
-		nm_utils_strbuf_append_str (&buf, &buf_len, "(null)");
-		goto out;
-	}
-
-	if (G_UNLIKELY (buf_len <= 2)) {
-		switch (buf_len) {
-		case 2:
-			*(buf++) = '^';
-			/* fall-through */
-		case 1:
-			*(buf++) = '\0';
-			break;
-		}
-		goto out;
-	}
-
-	*(buf++) = '"';
-	buf_len--;
-
-	nm_utils_strbuf_append_str (&buf, &buf_len, str);
-
-	/* if the string was too long we indicate truncation with a
-	 * '^' instead of a closing quote. */
-	if (G_UNLIKELY (buf_len <= 1)) {
-		switch (buf_len) {
-		case 1:
-			buf[-1] = '^';
-			break;
-		case 0:
-			buf[-2] = '^';
-			break;
-		default:
-			nm_assert_not_reached ();
-			break;
-		}
-	} else {
-		nm_assert (buf_len >= 2);
-		*(buf++) = '"';
-		*(buf++) = '\0';
-	}
-
-out:
-	return buf0;
-}
-
-/*****************************************************************************/
-
-char _nm_utils_to_string_buffer[];
-
-void
-nm_utils_to_string_buffer_init (char **buf, gsize *len)
-{
-	if (!*buf) {
-		*buf = _nm_utils_to_string_buffer;
-		*len = sizeof (_nm_utils_to_string_buffer);
-	}
-}
-
-gboolean
-nm_utils_to_string_buffer_init_null (gconstpointer obj, char **buf, gsize *len)
-{
-	nm_utils_to_string_buffer_init (buf, len);
-	if (!obj) {
-		g_strlcpy (*buf, "(null)", *len);
-		return FALSE;
-	}
-	return TRUE;
-}
-
-/*****************************************************************************/
-
-const char *
-nm_utils_flags2str (const NMUtilsFlags2StrDesc *descs,
-                    gsize n_descs,
-                    unsigned flags,
-                    char *buf,
-                    gsize len)
-{
-	gsize i;
-	char *p;
-
-#if NM_MORE_ASSERTS > 10
-	nm_assert (descs);
-	nm_assert (n_descs > 0);
-	for (i = 0; i < n_descs; i++) {
-		gsize j;
-
-		nm_assert (descs[i].name && descs[i].name[0]);
-		for (j = 0; j < i; j++)
-			nm_assert (descs[j].flag != descs[i].flag);
-	}
-#endif
-
-	nm_utils_to_string_buffer_init (&buf, &len);
-
-	if (!len)
-		return buf;
-
-	buf[0] = '\0';
-	p = buf;
-	if (!flags) {
-		for (i = 0; i < n_descs; i++) {
-			if (!descs[i].flag) {
-				nm_utils_strbuf_append_str (&p, &len, descs[i].name);
-				break;
-			}
-		}
-		return buf;
-	}
-
-	for (i = 0; flags && i < n_descs; i++) {
-		if (   descs[i].flag
-		    && NM_FLAGS_ALL (flags, descs[i].flag)) {
-			flags &= ~descs[i].flag;
-
-			if (buf[0] != '\0')
-				nm_utils_strbuf_append_c (&p, &len, ',');
-			nm_utils_strbuf_append_str (&p, &len, descs[i].name);
-		}
-	}
-	if (flags) {
-		if (buf[0] != '\0')
-			nm_utils_strbuf_append_c (&p, &len, ',');
-		nm_utils_strbuf_append (&p, &len, "0x%x", flags);
-	}
-	return buf;
-};
-
-/*****************************************************************************/
-
-/**
- * _nm_utils_ip4_prefix_to_netmask:
- * @prefix: a CIDR prefix
- *
- * Returns: the netmask represented by the prefix, in network byte order
- **/
-guint32
-_nm_utils_ip4_prefix_to_netmask (guint32 prefix)
-{
-	return prefix < 32 ? ~htonl(0xFFFFFFFF >> prefix) : 0xFFFFFFFF;
-}
-
-/**
- * _nm_utils_ip4_get_default_prefix:
- * @ip: an IPv4 address (in network byte order)
- *
- * When the Internet was originally set up, various ranges of IP addresses were
- * segmented into three network classes: A, B, and C.  This function will return
- * a prefix that is associated with the IP address specified defining where it
- * falls in the predefined classes.
- *
- * Returns: the default class prefix for the given IP
- **/
-/* The function is originally from ipcalc.c of Red Hat's initscripts. */
-guint32
-_nm_utils_ip4_get_default_prefix (guint32 ip)
-{
-	if (((ntohl (ip) & 0xFF000000) >> 24) <= 127)
-		return 8;  /* Class A - 255.0.0.0 */
-	else if (((ntohl (ip) & 0xFF000000) >> 24) <= 191)
-		return 16;  /* Class B - 255.255.0.0 */
-
-	return 24;  /* Class C - 255.255.255.0 */
-}
-
-gboolean
-nm_utils_ip_is_site_local (int addr_family,
-                           const void *address)
-{
-	in_addr_t addr4;
-
-	switch (addr_family) {
-	case AF_INET:
-		/* RFC1918 private addresses
-		 * 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 */
-		addr4 = ntohl (*((const in_addr_t *) address));
-		return    (addr4 & 0xff000000) == 0x0a000000
-		       || (addr4 & 0xfff00000) == 0xac100000
-		       || (addr4 & 0xffff0000) == 0xc0a80000;
-	case AF_INET6:
-		return IN6_IS_ADDR_SITELOCAL (address);
-	default:
-		g_return_val_if_reached (FALSE);
-	}
-}
-
-/*****************************************************************************/
-
-gboolean
-nm_utils_parse_inaddr_bin (int addr_family,
-                           const char *text,
-                           int *out_addr_family,
-                           gpointer out_addr)
-{
-	NMIPAddr addrbin;
-
-	g_return_val_if_fail (text, FALSE);
-
-	if (addr_family == AF_UNSPEC) {
-		g_return_val_if_fail (!out_addr || out_addr_family, FALSE);
-		addr_family = strchr (text, ':') ? AF_INET6 : AF_INET;
-	} else
-		g_return_val_if_fail (NM_IN_SET (addr_family, AF_INET, AF_INET6), FALSE);
-
-	if (inet_pton (addr_family, text, &addrbin) != 1)
-		return FALSE;
-
-	NM_SET_OUT (out_addr_family, addr_family);
-	if (out_addr)
-		nm_ip_addr_set (addr_family, out_addr, &addrbin);
-	return TRUE;
-}
-
-gboolean
-nm_utils_parse_inaddr (int addr_family,
-                       const char *text,
-                       char **out_addr)
-{
-	NMIPAddr addrbin;
-	char addrstr_buf[MAX (INET_ADDRSTRLEN, INET6_ADDRSTRLEN)];
-
-	if (!nm_utils_parse_inaddr_bin (addr_family, text, &addr_family, &addrbin))
-		return FALSE;
-	NM_SET_OUT (out_addr, g_strdup (inet_ntop (addr_family, &addrbin, addrstr_buf, sizeof (addrstr_buf))));
-	return TRUE;
-}
-
-gboolean
-nm_utils_parse_inaddr_prefix_bin (int addr_family,
-                                  const char *text,
-                                  int *out_addr_family,
-                                  gpointer out_addr,
-                                  int *out_prefix)
-{
-	gs_free char *addrstr_free = NULL;
-	int prefix = -1;
-	const char *slash;
-	const char *addrstr;
-	NMIPAddr addrbin;
-
-	g_return_val_if_fail (text, FALSE);
-
-	if (addr_family == AF_UNSPEC) {
-		g_return_val_if_fail (!out_addr || out_addr_family, FALSE);
-		addr_family = strchr (text, ':') ? AF_INET6 : AF_INET;
-	} else
-		g_return_val_if_fail (NM_IN_SET (addr_family, AF_INET, AF_INET6), FALSE);
-
-	slash = strchr (text, '/');
-	if (slash)
-		addrstr = addrstr_free = g_strndup (text, slash - text);
-	else
-		addrstr = text;
-
-	if (inet_pton (addr_family, addrstr, &addrbin) != 1)
-		return FALSE;
-
-	if (slash) {
-		/* For IPv4, `ip addr add` supports the prefix-length as a netmask. We don't
-		 * do that. */
-		prefix = _nm_utils_ascii_str_to_int64 (slash + 1, 10,
-		                                       0,
-		                                       addr_family == AF_INET ? 32 : 128,
-		                                       -1);
-		if (prefix == -1)
-			return FALSE;
-	}
-
-	NM_SET_OUT (out_addr_family, addr_family);
-	if (out_addr)
-		nm_ip_addr_set (addr_family, out_addr, &addrbin);
-	NM_SET_OUT (out_prefix, prefix);
-	return TRUE;
-}
-
-gboolean
-nm_utils_parse_inaddr_prefix (int addr_family,
-                              const char *text,
-                              char **out_addr,
-                              int *out_prefix)
-{
-	NMIPAddr addrbin;
-	char addrstr_buf[MAX (INET_ADDRSTRLEN, INET6_ADDRSTRLEN)];
-
-	if (!nm_utils_parse_inaddr_prefix_bin (addr_family, text, &addr_family, &addrbin, out_prefix))
-		return FALSE;
-	NM_SET_OUT (out_addr, g_strdup (inet_ntop (addr_family, &addrbin, addrstr_buf, sizeof (addrstr_buf))));
-	return TRUE;
-}
-
-/*****************************************************************************/
-
-/* _nm_utils_ascii_str_to_int64:
- *
- * A wrapper for g_ascii_strtoll, that checks whether the whole string
- * can be successfully converted to a number and is within a given
- * range. On any error, @fallback will be returned and %errno will be set
- * to a non-zero value. On success, %errno will be set to zero, check %errno
- * for errors. Any trailing or leading (ascii) white space is ignored and the
- * functions is locale independent.
- *
- * The function is guaranteed to return a value between @min and @max
- * (inclusive) or @fallback. Also, the parsing is rather strict, it does
- * not allow for any unrecognized characters, except leading and trailing
- * white space.
- **/
-gint64
-_nm_utils_ascii_str_to_int64 (const char *str, guint base, gint64 min, gint64 max, gint64 fallback)
-{
-	gint64 v;
-	const char *s = NULL;
-
-	if (str) {
-		while (g_ascii_isspace (str[0]))
-			str++;
-	}
-	if (!str || !str[0]) {
-		errno = EINVAL;
-		return fallback;
-	}
-
-	errno = 0;
-	v = g_ascii_strtoll (str, (char **) &s, base);
-
-	if (errno != 0)
-		return fallback;
-	if (s[0] != '\0') {
-		while (g_ascii_isspace (s[0]))
-			s++;
-		if (s[0] != '\0') {
-			errno = EINVAL;
-			return fallback;
-		}
-	}
-	if (v > max || v < min) {
-		errno = ERANGE;
-		return fallback;
-	}
-
-	return v;
-}
-
-guint64
-_nm_utils_ascii_str_to_uint64 (const char *str, guint base, guint64 min, guint64 max, guint64 fallback)
-{
-	guint64 v;
-	const char *s = NULL;
-
-	if (str) {
-		while (g_ascii_isspace (str[0]))
-			str++;
-	}
-	if (!str || !str[0]) {
-		errno = EINVAL;
-		return fallback;
-	}
-
-	errno = 0;
-	v = g_ascii_strtoull (str, (char **) &s, base);
-
-	if (errno != 0)
-		return fallback;
-	if (s[0] != '\0') {
-		while (g_ascii_isspace (s[0]))
-			s++;
-		if (s[0] != '\0') {
-			errno = EINVAL;
-			return fallback;
-		}
-	}
-	if (v > max || v < min) {
-		errno = ERANGE;
-		return fallback;
-	}
-
-	if (   v != 0
-	    && str[0] == '-') {
-		/* I don't know why, but g_ascii_strtoull() accepts minus signs ("-2" gives 18446744073709551614).
-		 * For "-0" that is OK, but otherwise not. */
-		errno = ERANGE;
-		return fallback;
-	}
-
-	return v;
-}
-
-/*****************************************************************************/
-
-/* like nm_strcmp_p(), suitable for g_ptr_array_sort_with_data().
- * g_ptr_array_sort() just casts nm_strcmp_p() to a function of different
- * signature. I guess, in glib there are knowledgeable people that ensure
- * that this additional argument doesn't cause problems due to different ABI
- * for every architecture that glib supports.
- * For NetworkManager, we'd rather avoid such stunts.
- **/
-int
-nm_strcmp_p_with_data (gconstpointer a, gconstpointer b, gpointer user_data)
-{
-	const char *s1 = *((const char **) a);
-	const char *s2 = *((const char **) b);
-
-	return strcmp (s1, s2);
-}
-
-int
-nm_cmp_uint32_p_with_data (gconstpointer p_a, gconstpointer p_b, gpointer user_data)
-{
-	const guint32 a = *((const guint32 *) p_a);
-	const guint32 b = *((const guint32 *) p_b);
-
-	if (a < b)
-		return -1;
-	if (a > b)
-		return 1;
-	return 0;
-}
-
-int
-nm_cmp_int2ptr_p_with_data (gconstpointer p_a, gconstpointer p_b, gpointer user_data)
-{
-	/* p_a and p_b are two pointers to a pointer, where the pointer is
-	 * interpreted as a integer using GPOINTER_TO_INT().
-	 *
-	 * That is the case of a hash-table that uses GINT_TO_POINTER() to
-	 * convert integers as pointers, and the resulting keys-as-array
-	 * array. */
-	const int a = GPOINTER_TO_INT (*((gconstpointer *) p_a));
-	const int b = GPOINTER_TO_INT (*((gconstpointer *) p_b));
-
-	if (a < b)
-		return -1;
-	if (a > b)
-		return 1;
-	return 0;
-}
-
-/*****************************************************************************/
-
-const char *
-nm_utils_dbus_path_get_last_component (const char *dbus_path)
-{
-	if (dbus_path) {
-		dbus_path = strrchr (dbus_path, '/');
-		if (dbus_path)
-			return dbus_path + 1;
-	}
-	return NULL;
-}
-
-static gint64
-_dbus_path_component_as_num (const char *p)
-{
-	gint64 n;
-
-	/* no odd stuff. No leading zeros, only a non-negative, decimal integer.
-	 *
-	 * Otherwise, there would be multiple ways to encode the same number "10"
-	 * and "010". That is just confusing. A number has no leading zeros,
-	 * if it has, it's not a number (as far as we are concerned here). */
-	if (p[0] == '0') {
-		if (p[1] != '\0')
-			return -1;
-		else
-			return 0;
-	}
-	if (!(p[0] >= '1' && p[0] <= '9'))
-		return -1;
-	if (!NM_STRCHAR_ALL (&p[1], ch, (ch >= '0' && ch <= '9')))
-		return -1;
-	n = _nm_utils_ascii_str_to_int64 (p, 10, 0, G_MAXINT64, -1);
-	nm_assert (n == -1 || nm_streq0 (p, nm_sprintf_bufa (100, "%"G_GINT64_FORMAT, n)));
-	return n;
-}
-
-int
-nm_utils_dbus_path_cmp (const char *dbus_path_a, const char *dbus_path_b)
-{
-	const char *l_a, *l_b;
-	gsize plen;
-	gint64 n_a, n_b;
-
-	/* compare function for two D-Bus paths. It behaves like
-	 * strcmp(), except, if both paths have the same prefix,
-	 * and both end in a (positive) number, then the paths
-	 * will be sorted by number. */
-
-	NM_CMP_SELF (dbus_path_a, dbus_path_b);
-
-	/* if one or both paths have no slash (and no last component)
-	 * compare the full paths directly. */
-	if (   !(l_a = nm_utils_dbus_path_get_last_component (dbus_path_a))
-	    || !(l_b = nm_utils_dbus_path_get_last_component (dbus_path_b)))
-		goto comp_full;
-
-	/* check if both paths have the same prefix (up to the last-component). */
-	plen = l_a - dbus_path_a;
-	if (plen != (l_b - dbus_path_b))
-		goto comp_full;
-	NM_CMP_RETURN (strncmp (dbus_path_a, dbus_path_b, plen));
-
-	n_a = _dbus_path_component_as_num (l_a);
-	n_b = _dbus_path_component_as_num (l_b);
-	if (n_a == -1 && n_b == -1)
-		goto comp_l;
-
-	/* both components must be convertiable to a number. If they are not,
-	 * (and only one of them is), then we must always strictly sort numeric parts
-	 * after non-numeric components. If we wouldn't, we wouldn't have
-	 * a total order.
-	 *
-	 * An example of a not total ordering would be:
-	 *   "8"   < "010"  (numeric)
-	 *   "0x"  < "8"    (lexical)
-	 *   "0x"  > "010"  (lexical)
-	 * We avoid this, by forcing that a non-numeric entry "0x" always sorts
-	 * before numeric entries.
-	 *
-	 * Additionally, _dbus_path_component_as_num() would also reject "010" as
-	 * not a valid number.
-	 */
-	if (n_a == -1)
-		return -1;
-	if (n_b == -1)
-		return 1;
-
-	NM_CMP_DIRECT (n_a, n_b);
-	nm_assert (nm_streq (dbus_path_a, dbus_path_b));
-	return 0;
-
-comp_full:
-	NM_CMP_DIRECT_STRCMP0 (dbus_path_a, dbus_path_b);
-	return 0;
-comp_l:
-	NM_CMP_DIRECT_STRCMP0 (l_a, l_b);
-	nm_assert (nm_streq (dbus_path_a, dbus_path_b));
-	return 0;
-}
-
-/*****************************************************************************/
-
-/**
- * nm_utils_strsplit_set:
- * @str: the string to split.
- * @delimiters: the set of delimiters. If %NULL, defaults to " \t\n",
- *   like bash's $IFS.
- * @allow_escaping: whether delimiters can be escaped by a backslash
- *
- * This is a replacement for g_strsplit_set() which avoids copying
- * each word once (the entire strv array), but instead copies it once
- * and all words point into that internal copy.
- *
- * Another difference from g_strsplit_set() is that this never returns
- * empty words. Multiple delimiters are combined and treated as one.
- *
- * If @allow_escaping is %TRUE, delimiters prefixed by a backslash are
- * not treated as a separator. Such delimiters and their escape
- * character are copied to the current word without unescaping them.
- *
- * Returns: %NULL if @str is %NULL or contains only delimiters.
- *   Otherwise, a %NULL terminated strv array containing non-empty
- *   words, split at the delimiter characters (delimiter characters
- *   are removed).
- *   The strings to which the result strv array points to are allocated
- *   after the returned result itself. Don't free the strings themself,
- *   but free everything with g_free().
- */
-const char **
-nm_utils_strsplit_set (const char *str, const char *delimiters, gboolean allow_escaping)
-{
-	const char **ptr, **ptr0;
-	gsize alloc_size, plen, i;
-	gsize str_len;
-	char *s0;
-	char *s;
-	guint8 delimiters_table[256];
-	gboolean escaped = FALSE;
-
-	if (!str)
-		return NULL;
-
-	/* initialize lookup table for delimiter */
-	if (!delimiters)
-		delimiters = " \t\n";
-	memset (delimiters_table, 0, sizeof (delimiters_table));
-	for (i = 0; delimiters[i]; i++)
-		delimiters_table[(guint8) delimiters[i]] = 1;
-
-#define _is_delimiter(ch, delimiters_table, allow_esc, esc) \
-	((delimiters_table)[(guint8) (ch)] != 0 && (!allow_esc || !esc))
-
-#define next_char(p, esc) \
-	G_STMT_START { \
-		if (esc) \
-			esc = FALSE; \
-		else \
-			esc = p[0] == '\\'; \
-		p++; \
-	} G_STMT_END
-
-	/* skip initial delimiters, and return of the remaining string is
-	 * empty. */
-	while (_is_delimiter (str[0], delimiters_table, allow_escaping, escaped))
-		next_char (str, escaped);
-
-	if (!str[0])
-		return NULL;
-
-	str_len = strlen (str) + 1;
-	alloc_size = 8;
-
-	/* we allocate the buffer larger, so to copy @str at the
-	 * end of it as @s0. */
-	ptr0 = g_malloc ((sizeof (const char *) * (alloc_size + 1)) + str_len);
-	s0 = (char *) &ptr0[alloc_size + 1];
-	memcpy (s0, str, str_len);
-
-	plen = 0;
-	s = s0;
-	ptr = ptr0;
-
-	while (TRUE) {
-		if (plen >= alloc_size) {
-			const char **ptr_old = ptr;
-
-			/* reallocate the buffer. Note that for now the string
-			 * continues to be in ptr0/s0. We fix that at the end. */
-			alloc_size *= 2;
-			ptr = g_malloc ((sizeof (const char *) * (alloc_size + 1)) + str_len);
-			memcpy (ptr, ptr_old, sizeof (const char *) * plen);
-			if (ptr_old != ptr0)
-				g_free (ptr_old);
-		}
-
-		ptr[plen++] = s;
-
-		nm_assert (s[0] && !_is_delimiter (s[0], delimiters_table, allow_escaping, escaped));
-
-		while (TRUE) {
-			next_char (s, escaped);
-			if (_is_delimiter (s[0], delimiters_table, allow_escaping, escaped))
-				break;
-			if (s[0] == '\0')
-				goto done;
-		}
-
-		s[0] = '\0';
-		next_char (s, escaped);
-		while (_is_delimiter (s[0], delimiters_table, allow_escaping, escaped))
-			next_char (s, escaped);
-		if (s[0] == '\0')
-			break;
-	}
-done:
-	ptr[plen] = NULL;
-
-	if (ptr != ptr0) {
-		/* we reallocated the buffer. We must copy over the
-		 * string @s0 and adjust the pointers. */
-		s = (char *) &ptr[alloc_size + 1];
-		memcpy (s, s0, str_len);
-		for (i = 0; i < plen; i++)
-			ptr[i] = &s[ptr[i] - s0];
-		g_free (ptr0);
-	}
-
-	return ptr;
-}
-
-/**
- * nm_utils_strv_find_first:
- * @list: the strv list to search
- * @len: the length of the list, or a negative value if @list is %NULL terminated.
- * @needle: the value to search for. The search is done using strcmp().
- *
- * Searches @list for @needle and returns the index of the first match (based
- * on strcmp()).
- *
- * For convenience, @list has type 'char**' instead of 'const char **'.
- *
- * Returns: index of first occurrence or -1 if @needle is not found in @list.
- */
-gssize
-nm_utils_strv_find_first (char **list, gssize len, const char *needle)
-{
-	gssize i;
-
-	if (len > 0) {
-		g_return_val_if_fail (list, -1);
-
-		if (!needle) {
-			/* if we search a list with known length, %NULL is a valid @needle. */
-			for (i = 0; i < len; i++) {
-				if (!list[i])
-					return i;
-			}
-		} else {
-			for (i = 0; i < len; i++) {
-				if (list[i] && !strcmp (needle, list[i]))
-					return i;
-			}
-		}
-	} else if (len < 0) {
-		g_return_val_if_fail (needle, -1);
-
-		if (list) {
-			for (i = 0; list[i]; i++) {
-				if (strcmp (needle, list[i]) == 0)
-					return i;
-			}
-		}
-	}
-	return -1;
-}
-
-char **
-_nm_utils_strv_cleanup (char **strv,
-                        gboolean strip_whitespace,
-                        gboolean skip_empty,
-                        gboolean skip_repeated)
-{
-	guint i, j;
-
-	if (!strv || !*strv)
-		return strv;
-
-	if (strip_whitespace) {
-		for (i = 0; strv[i]; i++)
-			g_strstrip (strv[i]);
-	}
-	if (!skip_empty && !skip_repeated)
-		return strv;
-	j = 0;
-	for (i = 0; strv[i]; i++) {
-		if (   (skip_empty && !*strv[i])
-		    || (skip_repeated && nm_utils_strv_find_first (strv, j, strv[i]) >= 0))
-			g_free (strv[i]);
-		else
-			strv[j++] = strv[i];
-	}
-	strv[j] = NULL;
-	return strv;
-}
-
-/*****************************************************************************/
-
-int
-_nm_utils_ascii_str_to_bool (const char *str,
-                             int default_value)
-{
-	gsize len;
-	char *s = NULL;
-
-	if (!str)
-		return default_value;
-
-	while (str[0] && g_ascii_isspace (str[0]))
-		str++;
-
-	if (!str[0])
-		return default_value;
-
-	len = strlen (str);
-	if (g_ascii_isspace (str[len - 1])) {
-		s = g_strdup (str);
-		g_strchomp (s);
-		str = s;
-	}
-
-	if (!g_ascii_strcasecmp (str, "true") || !g_ascii_strcasecmp (str, "yes") || !g_ascii_strcasecmp (str, "on") || !g_ascii_strcasecmp (str, "1"))
-		default_value = TRUE;
-	else if (!g_ascii_strcasecmp (str, "false") || !g_ascii_strcasecmp (str, "no") || !g_ascii_strcasecmp (str, "off") || !g_ascii_strcasecmp (str, "0"))
-		default_value = FALSE;
-	if (s)
-		g_free (s);
-	return default_value;
-}
-
-/*****************************************************************************/
-
-NM_CACHED_QUARK_FCN ("nm-utils-error-quark", nm_utils_error_quark)
-
-void
-nm_utils_error_set_cancelled (GError **error,
-                              gboolean is_disposing,
-                              const char *instance_name)
-{
-	if (is_disposing) {
-		g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_CANCELLED_DISPOSING,
-		             "Disposing %s instance",
-		             instance_name && *instance_name ? instance_name : "source");
-	} else {
-		g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CANCELLED,
-		                     "Request cancelled");
-	}
-}
-
-gboolean
-nm_utils_error_is_cancelled (GError *error,
-                             gboolean consider_is_disposing)
-{
-	if (error) {
-		if (error->domain == G_IO_ERROR)
-			return NM_IN_SET (error->code, G_IO_ERROR_CANCELLED);
-		if (consider_is_disposing) {
-			if (error->domain == NM_UTILS_ERROR)
-				return NM_IN_SET (error->code, NM_UTILS_ERROR_CANCELLED_DISPOSING);
-		}
-	}
-	return FALSE;
-}
-
-gboolean
-nm_utils_error_is_notfound (GError *error)
-{
-	if (error) {
-		if (error->domain == G_IO_ERROR)
-			return NM_IN_SET (error->code, G_IO_ERROR_NOT_FOUND);
-		if (error->domain == G_FILE_ERROR)
-			return NM_IN_SET (error->code, G_FILE_ERROR_NOENT);
-	}
-	return FALSE;
-}
-
-/*****************************************************************************/
-
-/**
- * nm_g_object_set_property:
- * @object: the target object
- * @property_name: the property name
- * @value: the #GValue to set
- * @error: (allow-none): optional error argument
- *
- * A reimplementation of g_object_set_property(), but instead
- * returning an error instead of logging a warning. All g_object_set*()
- * versions in glib require you to not pass invalid types or they will
- * log a g_warning() -- without reporting an error. We don't want that,
- * so we need to hack error checking around it.
- *
- * Returns: whether the value was successfully set.
- */
-gboolean
-nm_g_object_set_property (GObject *object,
-                          const char *property_name,
-                          const GValue *value,
-                          GError **error)
-{
-	GParamSpec *pspec;
-	nm_auto_unset_gvalue GValue tmp_value = G_VALUE_INIT;
-	GObjectClass *klass;
-
-	g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
-	g_return_val_if_fail (property_name != NULL, FALSE);
-	g_return_val_if_fail (G_IS_VALUE (value), FALSE);
-	g_return_val_if_fail (!error || !*error, FALSE);
-
-	/* g_object_class_find_property() does g_param_spec_get_redirect_target(),
-	 * where we differ from a plain g_object_set_property(). */
-	pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), property_name);
-
-	if (!pspec) {
-		g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
-		             _("object class '%s' has no property named '%s'"),
-		             G_OBJECT_TYPE_NAME (object),
-		             property_name);
-		return FALSE;
-	}
-	if (!(pspec->flags & G_PARAM_WRITABLE)) {
-		g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
-		             _("property '%s' of object class '%s' is not writable"),
-		             pspec->name,
-		             G_OBJECT_TYPE_NAME (object));
-		return FALSE;
-	}
-	if ((pspec->flags & G_PARAM_CONSTRUCT_ONLY)) {
-		g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
-		             _("construct property \"%s\" for object '%s' can't be set after construction"),
-		             pspec->name, G_OBJECT_TYPE_NAME (object));
-		return FALSE;
-	}
-
-	klass = g_type_class_peek (pspec->owner_type);
-	if (klass == NULL) {
-		g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
-		             _("'%s::%s' is not a valid property name; '%s' is not a GObject subtype"),
-		            g_type_name (pspec->owner_type), pspec->name, g_type_name (pspec->owner_type));
-		return FALSE;
-	}
-
-	/* provide a copy to work from, convert (if necessary) and validate */
-	g_value_init (&tmp_value, pspec->value_type);
-	if (!g_value_transform (value, &tmp_value)) {
-		g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
-		             _("unable to set property '%s' of type '%s' from value of type '%s'"),
-		             pspec->name,
-		             g_type_name (pspec->value_type),
-		             G_VALUE_TYPE_NAME (value));
-		return FALSE;
-	}
-	if (   g_param_value_validate (pspec, &tmp_value)
-	    && !(pspec->flags & G_PARAM_LAX_VALIDATION)) {
-		gs_free char *contents = g_strdup_value_contents (value);
-
-		g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
-		             _("value \"%s\" of type '%s' is invalid or out of range for property '%s' of type '%s'"),
-		             contents,
-		             G_VALUE_TYPE_NAME (value),
-		             pspec->name,
-		             g_type_name (pspec->value_type));
-		return FALSE;
-	}
-
-	g_object_set_property (object, property_name, &tmp_value);
-	return TRUE;
-}
-
-#define _set_property(object, property_name, gtype, gtype_set, value, error) \
-	G_STMT_START { \
-		nm_auto_unset_gvalue GValue gvalue = { 0 }; \
-		\
-		g_value_init (&gvalue, gtype); \
-		gtype_set (&gvalue, (value)); \
-		return nm_g_object_set_property ((object), (property_name), &gvalue, (error)); \
-	} G_STMT_END
-
-gboolean
-nm_g_object_set_property_string (GObject *object,
-                                 const char *property_name,
-                                 const char *value,
-                                 GError **error)
-{
-	_set_property (object, property_name, G_TYPE_STRING, g_value_set_string, value, error);
-}
-
-gboolean
-nm_g_object_set_property_string_static (GObject *object,
-                                        const char *property_name,
-                                        const char *value,
-                                        GError **error)
-{
-	_set_property (object, property_name, G_TYPE_STRING, g_value_set_static_string, value, error);
-}
-
-gboolean
-nm_g_object_set_property_string_take (GObject *object,
-                                      const char *property_name,
-                                      char *value,
-                                      GError **error)
-{
-	_set_property (object, property_name, G_TYPE_STRING, g_value_take_string, value, error);
-}
-
-gboolean
-nm_g_object_set_property_boolean (GObject *object,
-                                  const char *property_name,
-                                  gboolean value,
-                                  GError **error)
-{
-	_set_property (object, property_name, G_TYPE_BOOLEAN, g_value_set_boolean, !!value, error);
-}
-
-gboolean
-nm_g_object_set_property_char (GObject *object,
-                               const char *property_name,
-                               gint8 value,
-                               GError **error)
-{
-	/* glib says about G_TYPE_CHAR:
-	 *
-	 * The type designated by G_TYPE_CHAR is unconditionally an 8-bit signed integer.
-	 *
-	 * This is always a (signed!) char. */
-	_set_property (object, property_name, G_TYPE_CHAR, g_value_set_schar, value, error);
-}
-
-gboolean
-nm_g_object_set_property_uchar (GObject *object,
-                                const char *property_name,
-                                guint8 value,
-                                GError **error)
-{
-	_set_property (object, property_name, G_TYPE_UCHAR, g_value_set_uchar, value, error);
-}
-
-gboolean
-nm_g_object_set_property_int (GObject *object,
-                              const char *property_name,
-                              int value,
-                              GError **error)
-{
-	_set_property (object, property_name, G_TYPE_INT, g_value_set_int, value, error);
-}
-
-gboolean
-nm_g_object_set_property_int64 (GObject *object,
-                                const char *property_name,
-                                gint64 value,
-                                GError **error)
-{
-	_set_property (object, property_name, G_TYPE_INT64, g_value_set_int64, value, error);
-}
-
-gboolean
-nm_g_object_set_property_uint (GObject *object,
-                               const char *property_name,
-                               guint value,
-                               GError **error)
-{
-	_set_property (object, property_name, G_TYPE_UINT, g_value_set_uint, value, error);
-}
-
-gboolean
-nm_g_object_set_property_uint64 (GObject *object,
-                                 const char *property_name,
-                                 guint64 value,
-                                 GError **error)
-{
-	_set_property (object, property_name, G_TYPE_UINT64, g_value_set_uint64, value, error);
-}
-
-gboolean
-nm_g_object_set_property_flags (GObject *object,
-                                const char *property_name,
-                                GType gtype,
-                                guint value,
-                                GError **error)
-{
-	nm_assert (({
-	                nm_auto_unref_gtypeclass GTypeClass *gtypeclass = g_type_class_ref (gtype);
-	                G_IS_FLAGS_CLASS (gtypeclass);
-	           }));
-	_set_property (object, property_name, gtype, g_value_set_flags, value, error);
-}
-
-gboolean
-nm_g_object_set_property_enum (GObject *object,
-                               const char *property_name,
-                               GType gtype,
-                               int value,
-                               GError **error)
-{
-	nm_assert (({
-	                nm_auto_unref_gtypeclass GTypeClass *gtypeclass = g_type_class_ref (gtype);
-	                G_IS_ENUM_CLASS (gtypeclass);
-	           }));
-	_set_property (object, property_name, gtype, g_value_set_enum, value, error);
-}
-
-GParamSpec *
-nm_g_object_class_find_property_from_gtype (GType gtype,
-                                            const char *property_name)
-{
-	nm_auto_unref_gtypeclass GObjectClass *gclass = NULL;
-
-	gclass = g_type_class_ref (gtype);
-	return g_object_class_find_property (gclass, property_name);
-}
-
-/*****************************************************************************/
-
-/**
- * nm_g_type_find_implementing_class_for_property:
- * @gtype: the GObject type which has a property @pname
- * @pname: the name of the property to look up
- *
- * This is only a helper function for printf debugging. It's not
- * used in actual code. Hence, the function just asserts that
- * @pname and @gtype arguments are suitable. It cannot fail.
- *
- * Returns: the most ancestor type of @gtype, that
- *   implements the property @pname. It means, it
- *   searches the type hierarchy to find the type
- *   that added @pname.
- */
-GType
-nm_g_type_find_implementing_class_for_property (GType gtype,
-                                                const char *pname)
-{
-	nm_auto_unref_gtypeclass GObjectClass *klass = NULL;
-	GParamSpec *pspec;
-
-	g_return_val_if_fail (pname, G_TYPE_INVALID);
-
-	klass = g_type_class_ref (gtype);
-	g_return_val_if_fail (G_IS_OBJECT_CLASS (klass), G_TYPE_INVALID);
-
-	pspec = g_object_class_find_property (klass, pname);
-	g_return_val_if_fail (pspec, G_TYPE_INVALID);
-
-	gtype = G_TYPE_FROM_CLASS (klass);
-
-	while (TRUE) {
-		nm_auto_unref_gtypeclass GObjectClass *k = NULL;
-
-		k = g_type_class_ref (g_type_parent (gtype));
-
-		g_return_val_if_fail (G_IS_OBJECT_CLASS (k), G_TYPE_INVALID);
-
-		if (g_object_class_find_property (k, pname) != pspec)
-			return gtype;
-
-		gtype = G_TYPE_FROM_CLASS (k);
-	}
-}
-
-/*****************************************************************************/
-
-static void
-_str_append_escape (GString *s, char ch)
-{
-	g_string_append_c (s, '\\');
-	g_string_append_c (s, '0' + ((((guchar) ch) >> 6) & 07));
-	g_string_append_c (s, '0' + ((((guchar) ch) >> 3) & 07));
-	g_string_append_c (s, '0' + ( ((guchar) ch)       & 07));
-}
-
-gconstpointer
-nm_utils_buf_utf8safe_unescape (const char *str, gsize *out_len, gpointer *to_free)
-{
-	GString *gstr;
-	gsize len;
-	const char *s;
-
-	g_return_val_if_fail (to_free, NULL);
-	g_return_val_if_fail (out_len, NULL);
-
-	if (!str) {
-		*out_len = 0;
-		*to_free = NULL;
-		return NULL;
-	}
-
-	len = strlen (str);
-
-	s = memchr (str, '\\', len);
-	if (!s) {
-		*out_len = len;
-		*to_free = NULL;
-		return str;
-	}
-
-	gstr = g_string_new_len (NULL, len);
-
-	g_string_append_len (gstr, str, s - str);
-	str = s;
-
-	for (;;) {
-		char ch;
-		guint v;
-
-		nm_assert (str[0] == '\\');
-
-		ch = (++str)[0];
-
-		if (ch == '\0') {
-			// error. Trailing '\\'
-			break;
-		}
-
-		if (ch >= '0' && ch <= '9') {
-			v = ch - '0';
-			ch = (++str)[0];
-			if (ch >= '0' && ch <= '7') {
-				v = v * 8 + (ch - '0');
-				ch = (++str)[0];
-				if (ch >= '0' && ch <= '7') {
-					v = v * 8 + (ch - '0');
-					++str;
-				}
-			}
-			ch = v;
-		} else {
-			switch (ch) {
-			case 'b': ch = '\b'; break;
-			case 'f': ch = '\f'; break;
-			case 'n': ch = '\n'; break;
-			case 'r': ch = '\r'; break;
-			case 't': ch = '\t'; break;
-			case 'v': ch = '\v'; break;
-			default:
-				/* Here we handle "\\\\", but all other unexpected escape sequences are really a bug.
-				 * Take them literally, after removing the escape character */
-				break;
-			}
-			str++;
-		}
-
-		g_string_append_c (gstr, ch);
-
-		s = strchr (str, '\\');
-		if (!s) {
-			g_string_append (gstr, str);
-			break;
-		}
-
-		g_string_append_len (gstr, str, s - str);
-		str = s;
-	}
-
-	*out_len = gstr->len;
-	*to_free = gstr->str;
-	return g_string_free (gstr, FALSE);
-}
-
-/**
- * nm_utils_buf_utf8safe_escape:
- * @buf: byte array, possibly in utf-8 encoding, may have NUL characters.
- * @buflen: the length of @buf in bytes, or -1 if @buf is a NUL terminated
- *   string.
- * @flags: #NMUtilsStrUtf8SafeFlags flags
- * @to_free: (out): return the pointer location of the string
- *   if a copying was necessary.
- *
- * Based on the assumption, that @buf contains UTF-8 encoded bytes,
- * this will return valid UTF-8 sequence, and invalid sequences
- * will be escaped with backslash (C escaping, like g_strescape()).
- * This is sanitize non UTF-8 characters. The result is valid
- * UTF-8.
- *
- * The operation can be reverted with nm_utils_buf_utf8safe_unescape().
- * Note that if, and only if @buf contains no NUL bytes, the operation
- * can also be reverted with g_strcompress().
- *
- * Depending on @flags, valid UTF-8 characters are not escaped at all
- * (except the escape character '\\'). This is the difference to g_strescape(),
- * which escapes all non-ASCII characters. This allows to pass on
- * valid UTF-8 characters as-is and can be directly shown to the user
- * as UTF-8 -- with exception of the backslash escape character,
- * invalid UTF-8 sequences, and other (depending on @flags).
- *
- * Returns: the escaped input buffer, as valid UTF-8. If no escaping
- *   is necessary, it returns the input @buf. Otherwise, an allocated
- *   string @to_free is returned which must be freed by the caller
- *   with g_free. The escaping can be reverted by g_strcompress().
- **/
-const char *
-nm_utils_buf_utf8safe_escape (gconstpointer buf, gssize buflen, NMUtilsStrUtf8SafeFlags flags, char **to_free)
-{
-	const char *const str = buf;
-	const char *p = NULL;
-	const char *s;
-	gboolean nul_terminated = FALSE;
-	GString *gstr;
-
-	g_return_val_if_fail (to_free, NULL);
-
-	*to_free = NULL;
-
-	if (buflen == 0)
-		return NULL;
-
-	if (buflen < 0) {
-		if (!str)
-			return NULL;
-		buflen = strlen (str);
-		if (buflen == 0)
-			return str;
-		nul_terminated = TRUE;
-	}
-
-	if (   g_utf8_validate (str, buflen, &p)
-	    && nul_terminated) {
-		/* note that g_utf8_validate() does not allow NUL character inside @str. Good.
-		 * We can treat @str like a NUL terminated string. */
-		if (!NM_STRCHAR_ANY (str, ch,
-		                        (   ch == '\\' \
-		                         || (   NM_FLAGS_HAS (flags, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL) \
-		                             && ch < ' ') \
-		                         || (   NM_FLAGS_HAS (flags, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_NON_ASCII) \
-		                             && ((guchar) ch) >= 127))))
-			return str;
-	}
-
-	gstr = g_string_sized_new (buflen + 5);
-
-	s = str;
-	do {
-		buflen -= p - s;
-		nm_assert (buflen >= 0);
-
-		for (; s < p; s++) {
-			char ch = s[0];
-
-			if (ch == '\\')
-				g_string_append (gstr, "\\\\");
-			else if (   (   NM_FLAGS_HAS (flags, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL) \
-			             && ch < ' ') \
-			         || (   NM_FLAGS_HAS (flags, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_NON_ASCII) \
-			             && ((guchar) ch) >= 127))
-				_str_append_escape (gstr, ch);
-			else
-				g_string_append_c (gstr, ch);
-		}
-
-		if (buflen <= 0)
-			break;
-
-		_str_append_escape (gstr, p[0]);
-
-		buflen--;
-		if (buflen == 0)
-			break;
-
-		s = &p[1];
-		g_utf8_validate (s, buflen, &p);
-	} while (TRUE);
-
-	*to_free = g_string_free (gstr, FALSE);
-	return *to_free;
-}
-
-const char *
-nm_utils_buf_utf8safe_escape_bytes (GBytes *bytes, NMUtilsStrUtf8SafeFlags flags, char **to_free)
-{
-	gconstpointer p;
-	gsize l;
-
-	if (bytes)
-		p = g_bytes_get_data (bytes, &l);
-	else {
-		p = NULL;
-		l = 0;
-	}
-
-	return nm_utils_buf_utf8safe_escape (p, l, flags, to_free);
-}
-
-/*****************************************************************************/
-
-const char *
-nm_utils_str_utf8safe_unescape (const char *str, char **to_free)
-{
-	g_return_val_if_fail (to_free, NULL);
-
-	if (!str || !strchr (str, '\\')) {
-		*to_free = NULL;
-		return str;
-	}
-	return (*to_free = g_strcompress (str));
-}
-
-/**
- * nm_utils_str_utf8safe_escape:
- * @str: NUL terminated input string, possibly in utf-8 encoding
- * @flags: #NMUtilsStrUtf8SafeFlags flags
- * @to_free: (out): return the pointer location of the string
- *   if a copying was necessary.
- *
- * Returns the possible non-UTF-8 NUL terminated string @str
- * and uses backslash escaping (C escaping, like g_strescape())
- * to sanitize non UTF-8 characters. The result is valid
- * UTF-8.
- *
- * The operation can be reverted with g_strcompress() or
- * nm_utils_str_utf8safe_unescape().
- *
- * Depending on @flags, valid UTF-8 characters are not escaped at all
- * (except the escape character '\\'). This is the difference to g_strescape(),
- * which escapes all non-ASCII characters. This allows to pass on
- * valid UTF-8 characters as-is and can be directly shown to the user
- * as UTF-8 -- with exception of the backslash escape character,
- * invalid UTF-8 sequences, and other (depending on @flags).
- *
- * Returns: the escaped input string, as valid UTF-8. If no escaping
- *   is necessary, it returns the input @str. Otherwise, an allocated
- *   string @to_free is returned which must be freed by the caller
- *   with g_free. The escaping can be reverted by g_strcompress().
- **/
-const char *
-nm_utils_str_utf8safe_escape (const char *str, NMUtilsStrUtf8SafeFlags flags, char **to_free)
-{
-	return nm_utils_buf_utf8safe_escape (str, -1, flags, to_free);
-}
-
-/**
- * nm_utils_str_utf8safe_escape_cp:
- * @str: NUL terminated input string, possibly in utf-8 encoding
- * @flags: #NMUtilsStrUtf8SafeFlags flags
- *
- * Like nm_utils_str_utf8safe_escape(), except the returned value
- * is always a copy of the input and must be freed by the caller.
- *
- * Returns: the escaped input string in UTF-8 encoding. The returned
- *   value should be freed with g_free().
- *   The escaping can be reverted by g_strcompress().
- **/
-char *
-nm_utils_str_utf8safe_escape_cp (const char *str, NMUtilsStrUtf8SafeFlags flags)
-{
-	char *s;
-
-	nm_utils_str_utf8safe_escape (str, flags, &s);
-	return s ?: g_strdup (str);
-}
-
-char *
-nm_utils_str_utf8safe_unescape_cp (const char *str)
-{
-	return str ? g_strcompress (str) : NULL;
-}
-
-char *
-nm_utils_str_utf8safe_escape_take (char *str, NMUtilsStrUtf8SafeFlags flags)
-{
-	char *str_to_free;
-
-	nm_utils_str_utf8safe_escape (str, flags, &str_to_free);
-	if (str_to_free) {
-		g_free (str);
-		return str_to_free;
-	}
-	return str;
-}
-
-/*****************************************************************************/
-
-/* taken from systemd's fd_wait_for_event(). Note that the timeout
- * is here in nano-seconds, not micro-seconds. */
-int
-nm_utils_fd_wait_for_event (int fd, int event, gint64 timeout_ns)
-{
-	struct pollfd pollfd = {
-		.fd = fd,
-		.events = event,
-	};
-	struct timespec ts, *pts;
-	int r;
-
-	if (timeout_ns < 0)
-		pts = NULL;
-	else {
-		ts.tv_sec = (time_t) (timeout_ns / NM_UTILS_NS_PER_SECOND);
-		ts.tv_nsec = (long int) (timeout_ns % NM_UTILS_NS_PER_SECOND);
-		pts = &ts;
-	}
-
-	r = ppoll (&pollfd, 1, pts, NULL);
-	if (r < 0)
-		return -NM_ERRNO_NATIVE (errno);
-	if (r == 0)
-		return 0;
-	return pollfd.revents;
-}
-
-/* taken from systemd's loop_read() */
-ssize_t
-nm_utils_fd_read_loop (int fd, void *buf, size_t nbytes, bool do_poll)
-{
-	uint8_t *p = buf;
-	ssize_t n = 0;
-
-	g_return_val_if_fail (fd >= 0, -EINVAL);
-	g_return_val_if_fail (buf, -EINVAL);
-
-	/* If called with nbytes == 0, let's call read() at least
-	 * once, to validate the operation */
-
-	if (nbytes > (size_t) SSIZE_MAX)
-		return -EINVAL;
-
-	do {
-		ssize_t k;
-
-		k = read (fd, p, nbytes);
-		if (k < 0) {
-			int errsv = errno;
-
-			if (errsv == EINTR)
-				continue;
-
-			if (errsv == EAGAIN && do_poll) {
-
-				/* We knowingly ignore any return value here,
-				 * and expect that any error/EOF is reported
-				 * via read() */
-
-				(void) nm_utils_fd_wait_for_event (fd, POLLIN, -1);
-				continue;
-			}
-
-			return n > 0 ? n : -NM_ERRNO_NATIVE (errsv);
-		}
-
-		if (k == 0)
-			return n;
-
-		g_assert ((size_t) k <= nbytes);
-
-		p += k;
-		nbytes -= k;
-		n += k;
-	} while (nbytes > 0);
-
-	return n;
-}
-
-/* taken from systemd's loop_read_exact() */
-int
-nm_utils_fd_read_loop_exact (int fd, void *buf, size_t nbytes, bool do_poll)
-{
-	ssize_t n;
-
-	n = nm_utils_fd_read_loop (fd, buf, nbytes, do_poll);
-	if (n < 0)
-		return (int) n;
-	if ((size_t) n != nbytes)
-		return -EIO;
-
-	return 0;
-}
-
-NMUtilsNamedValue *
-nm_utils_named_values_from_str_dict (GHashTable *hash, guint *out_len)
-{
-	GHashTableIter iter;
-	NMUtilsNamedValue *values;
-	guint i, len;
-
-	if (   !hash
-	    || !(len = g_hash_table_size (hash))) {
-		NM_SET_OUT (out_len, 0);
-		return NULL;
-	}
-
-	i = 0;
-	values = g_new (NMUtilsNamedValue, len + 1);
-	g_hash_table_iter_init (&iter, hash);
-	while (g_hash_table_iter_next (&iter,
-	                               (gpointer *) &values[i].name,
-	                               (gpointer *) &values[i].value_ptr))
-		i++;
-	nm_assert (i == len);
-	values[i].name = NULL;
-	values[i].value_ptr = NULL;
-
-	if (len > 1) {
-		g_qsort_with_data (values, len, sizeof (values[0]),
-		                   nm_utils_named_entry_cmp_with_data, NULL);
-	}
-
-	NM_SET_OUT (out_len, len);
-	return values;
-}
-
-gpointer *
-nm_utils_hash_keys_to_array (GHashTable *hash,
-                             GCompareDataFunc compare_func,
-                             gpointer user_data,
-                             guint *out_len)
-{
-	guint len;
-	gpointer *keys;
-
-	/* by convention, we never return an empty array. In that
-	 * case, always %NULL. */
-	if (   !hash
-	    || g_hash_table_size (hash) == 0) {
-		NM_SET_OUT (out_len, 0);
-		return NULL;
-	}
-
-	keys = g_hash_table_get_keys_as_array (hash, &len);
-	if (   len > 1
-	    && compare_func) {
-		g_qsort_with_data (keys,
-		                   len,
-		                   sizeof (gpointer),
-		                   compare_func,
-		                   user_data);
-	}
-	NM_SET_OUT (out_len, len);
-	return keys;
-}
-
-char **
-nm_utils_strv_make_deep_copied (const char **strv)
-{
-	gsize i;
-
-	/* it takes a strv dictionary, and copies each
-	 * strings. Note that this updates @strv *in-place*
-	 * and returns it. */
-
-	if (!strv)
-		return NULL;
-	for (i = 0; strv[i]; i++)
-		strv[i] = g_strdup (strv[i]);
-
-	return (char **) strv;
-}
-
-/*****************************************************************************/
-
-gssize
-nm_utils_ptrarray_find_binary_search (gconstpointer *list,
-                                      gsize len,
-                                      gconstpointer needle,
-                                      GCompareDataFunc cmpfcn,
-                                      gpointer user_data,
-                                      gssize *out_idx_first,
-                                      gssize *out_idx_last)
-{
-	gssize imin, imax, imid, i2min, i2max, i2mid;
-	int cmp;
-
-	g_return_val_if_fail (list || !len, ~((gssize) 0));
-	g_return_val_if_fail (cmpfcn, ~((gssize) 0));
-
-	imin = 0;
-	if (len > 0) {
-		imax = len - 1;
-
-		while (imin <= imax) {
-			imid = imin + (imax - imin) / 2;
-
-			cmp = cmpfcn (list[imid], needle, user_data);
-			if (cmp == 0) {
-				/* we found a matching entry at index imid.
-				 *
-				 * Does the caller request the first/last index as well (in case that
-				 * there are multiple entries which compare equal). */
-
-				if (out_idx_first) {
-					i2min = imin;
-					i2max = imid + 1;
-					while (i2min <= i2max) {
-						i2mid = i2min + (i2max - i2min) / 2;
-
-						cmp = cmpfcn (list[i2mid], needle, user_data);
-						if (cmp == 0)
-							i2max = i2mid -1;
-						else {
-							nm_assert (cmp < 0);
-							i2min = i2mid + 1;
-						}
-					}
-					*out_idx_first = i2min;
-				}
-				if (out_idx_last) {
-					i2min = imid + 1;
-					i2max = imax;
-					while (i2min <= i2max) {
-						i2mid = i2min + (i2max - i2min) / 2;
-
-						cmp = cmpfcn (list[i2mid], needle, user_data);
-						if (cmp == 0)
-							i2min = i2mid + 1;
-						else {
-							nm_assert (cmp > 0);
-							i2max = i2mid - 1;
-						}
-					}
-					*out_idx_last = i2min - 1;
-				}
-				return imid;
-			}
-
-			if (cmp < 0)
-				imin = imid + 1;
-			else
-				imax = imid - 1;
-		}
-	}
-
-	/* return the inverse of @imin. This is a negative number, but
-	 * also is ~imin the position where the value should be inserted. */
-	imin = ~imin;
-	NM_SET_OUT (out_idx_first, imin);
-	NM_SET_OUT (out_idx_last, imin);
-	return imin;
-}
-
-/*****************************************************************************/
-
-/**
- * nm_utils_array_find_binary_search:
- * @list: the list to search. It must be sorted according to @cmpfcn ordering.
- * @elem_size: the size in bytes of each element in the list
- * @len: the number of elements in @list
- * @needle: the value that is searched
- * @cmpfcn: the compare function. The elements @list are passed as first
- *   argument to @cmpfcn, while @needle is passed as second. Usually, the
- *   needle is the same data type as inside the list, however, that is
- *   not necessary, as long as @cmpfcn takes care to cast the two arguments
- *   accordingly.
- * @user_data: optional argument passed to @cmpfcn
- *
- * Performs binary search for @needle in @list. On success, returns the
- * (non-negative) index where the compare function found the searched element.
- * On success, it returns a negative value. Note that the return negative value
- * is the bitwise inverse of the position where the element should be inserted.
- *
- * If the list contains multiple matching elements, an arbitrary index is
- * returned.
- *
- * Returns: the index to the element in the list, or the (negative, bitwise inverted)
- *   position where it should be.
- */
-gssize
-nm_utils_array_find_binary_search (gconstpointer list,
-                                   gsize elem_size,
-                                   gsize len,
-                                   gconstpointer needle,
-                                   GCompareDataFunc cmpfcn,
-                                   gpointer user_data)
-{
-	gssize imin, imax, imid;
-	int cmp;
-
-	g_return_val_if_fail (list || !len, ~((gssize) 0));
-	g_return_val_if_fail (cmpfcn, ~((gssize) 0));
-	g_return_val_if_fail (elem_size > 0, ~((gssize) 0));
-
-	imin = 0;
-	if (len == 0)
-		return ~imin;
-
-	imax = len - 1;
-
-	while (imin <= imax) {
-		imid = imin + (imax - imin) / 2;
-
-		cmp = cmpfcn (&((const char *) list)[elem_size * imid], needle, user_data);
-		if (cmp == 0)
-			return imid;
-
-		if (cmp < 0)
-			imin = imid + 1;
-		else
-			imax = imid - 1;
-	}
-
-	/* return the inverse of @imin. This is a negative number, but
-	 * also is ~imin the position where the value should be inserted. */
-	return ~imin;
-}
-
-/*****************************************************************************/
-
-/**
- * nm_utils_hash_table_equal:
- * @a: one #GHashTable
- * @b: other #GHashTable
- * @treat_null_as_empty: if %TRUE, when either @a or @b is %NULL, it is
- *   treated like an empty hash. It means, a %NULL hash will compare equal
- *   to an empty hash.
- * @equal_func: the equality function, for comparing the values.
- *   If %NULL, the values are not compared. In that case, the function
- *   only checks, if both dictionaries have the same keys -- according
- *   to @b's key equality function.
- *   Note that the values of @a will be passed as first argument
- *   to @equal_func.
- *
- * Compares two hash tables, whether they have equal content.
- * This only makes sense, if @a and @b have the same key types and
- * the same key compare-function.
- *
- * Returns: %TRUE, if both dictionaries have the same content.
- */
-gboolean
-nm_utils_hash_table_equal (const GHashTable *a,
-                           const GHashTable *b,
-                           gboolean treat_null_as_empty,
-                           NMUtilsHashTableEqualFunc equal_func)
-{
-	guint n;
-	GHashTableIter iter;
-	gconstpointer key, v_a, v_b;
-
-	if (a == b)
-		return TRUE;
-	if (!treat_null_as_empty) {
-		if (!a || !b)
-			return FALSE;
-	}
-
-	n = a ? g_hash_table_size ((GHashTable *) a) : 0;
-	if (n != (b ? g_hash_table_size ((GHashTable *) b) : 0))
-		return FALSE;
-
-	if (n > 0) {
-		g_hash_table_iter_init (&iter, (GHashTable *) a);
-		while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &v_a)) {
-			if (!g_hash_table_lookup_extended ((GHashTable *) b, key, NULL, (gpointer *) &v_b))
-				return FALSE;
-			if (   equal_func
-			    && !equal_func (v_a, v_b))
-				return FALSE;
-		}
-	}
-
-	return TRUE;
-}
-
-/*****************************************************************************/
-
-/**
- * nm_utils_get_start_time_for_pid:
- * @pid: the process identifier
- * @out_state: return the state character, like R, S, Z. See `man 5 proc`.
- * @out_ppid: parent process id
- *
- * Originally copied from polkit source (src/polkit/polkitunixprocess.c)
- * and adjusted.
- *
- * Returns: the timestamp when the process started (by parsing /proc/$PID/stat).
- * If an error occurs (e.g. the process does not exist), 0 is returned.
- *
- * The returned start time counts since boot, in the unit HZ (with HZ usually being (1/100) seconds)
- **/
-guint64
-nm_utils_get_start_time_for_pid (pid_t pid, char *out_state, pid_t *out_ppid)
-{
-	guint64 start_time;
-	char filename[256];
-	gs_free char *contents = NULL;
-	size_t length;
-	gs_free const char **tokens = NULL;
-	char *p;
-	char state = ' ';
-	gint64 ppid = 0;
-
-	start_time = 0;
-	contents = NULL;
-
-	g_return_val_if_fail (pid > 0, 0);
-
-	nm_sprintf_buf (filename, "/proc/%"G_GUINT64_FORMAT"/stat", (guint64) pid);
-
-	if (!g_file_get_contents (filename, &contents, &length, NULL))
-		goto fail;
-
-	/* start time is the token at index 19 after the '(process name)' entry - since only this
-	 * field can contain the ')' character, search backwards for this to avoid malicious
-	 * processes trying to fool us
-	 */
-	p = strrchr (contents, ')');
-	if (!p)
-		goto fail;
-	p += 2; /* skip ') ' */
-	if (p - contents >= (int) length)
-		goto fail;
-
-	state = p[0];
-
-	tokens = nm_utils_strsplit_set (p, " ", FALSE);
-
-	if (NM_PTRARRAY_LEN (tokens) < 20)
-		goto fail;
-
-	if (out_ppid) {
-		ppid = _nm_utils_ascii_str_to_int64 (tokens[1], 10, 1, G_MAXINT, 0);
-		if (ppid == 0)
-			goto fail;
-	}
-
-	start_time = _nm_utils_ascii_str_to_int64 (tokens[19], 10, 1, G_MAXINT64, 0);
-	if (start_time == 0)
-		goto fail;
-
-	NM_SET_OUT (out_state, state);
-	NM_SET_OUT (out_ppid, ppid);
-	return start_time;
-
-fail:
-	NM_SET_OUT (out_state, ' ');
-	NM_SET_OUT (out_ppid, 0);
-	return 0;
-}
-
-/*****************************************************************************/
-
-/**
- * _nm_utils_strv_sort:
- * @strv: pointer containing strings that will be sorted
- *   in-place, %NULL is allowed, unless @len indicates
- *   that there are more elements.
- * @len: the number of elements in strv. If negative,
- *   strv must be a NULL terminated array and the length
- *   will be calculated first. If @len is a positive
- *   number, all first @len elements in @strv must be
- *   non-NULL, valid strings.
- *
- * Ascending sort of the array @strv inplace, using plain strcmp() string
- * comparison.
- */
-void
-_nm_utils_strv_sort (const char **strv, gssize len)
-{
-	gsize l;
-
-	l = len < 0 ? (gsize) NM_PTRARRAY_LEN (strv) : (gsize) len;
-
-	if (l <= 1)
-		return;
-
-	nm_assert (l <= (gsize) G_MAXINT);
-
-	g_qsort_with_data (strv,
-	                   l,
-	                   sizeof (const char *),
-	                   nm_strcmp_p_with_data,
-	                   NULL);
-}
-
-/*****************************************************************************/
-
-gpointer
-_nm_utils_user_data_pack (int nargs, gconstpointer *args)
-{
-	int i;
-	gpointer *data;
-
-	nm_assert (nargs > 0);
-	nm_assert (args);
-
-	data = g_slice_alloc (((gsize) nargs) * sizeof (gconstpointer));
-	for (i = 0; i < nargs; i++)
-		data[i] = (gpointer) args[i];
-	return data;
-}
-
-void
-_nm_utils_user_data_unpack (gpointer user_data, int nargs, ...)
-{
-	gpointer *data = user_data;
-	va_list ap;
-	int i;
-
-	nm_assert (data);
-	nm_assert (nargs > 0);
-
-	va_start (ap, nargs);
-	for (i = 0; i < nargs; i++) {
-		gpointer *dst;
-
-		dst = va_arg (ap, gpointer *);
-		nm_assert (dst);
-
-		*dst = data[i];
-	}
-	va_end (ap);
-
-	g_slice_free1 (((gsize) nargs) * sizeof (gconstpointer), user_data);
-}
-
-/*****************************************************************************/
-
-#define IS_SPACE(c) NM_IN_SET ((c), ' ', '\t')
-
-const char *
-_nm_utils_escape_spaces (const char *str, char **to_free)
-{
-	const char *ptr = str;
-	char *ret, *r;
-
-	*to_free = NULL;
-
-	if (!str)
-		return NULL;
-
-	while (TRUE) {
-		if (!*ptr)
-			return str;
-		if (IS_SPACE (*ptr))
-			break;
-		ptr++;
-	}
-
-	ptr = str;
-	ret = g_new (char, strlen (str) * 2 + 1);
-	r = ret;
-	*to_free = ret;
-	while (*ptr) {
-		if (IS_SPACE (*ptr))
-			*r++ = '\\';
-		*r++ = *ptr++;
-	}
-	*r = '\0';
-
-	return ret;
-}
-
-char *
-_nm_utils_unescape_spaces (char *str)
-{
-	guint i, j = 0;
-
-	if (!str)
-		return NULL;
-
-	for (i = 0; str[i]; i++) {
-		if (str[i] == '\\' && IS_SPACE (str[i+1]))
-			i++;
-		str[j++] = str[i];
-	}
-	str[j] = '\0';
-
-	return str;
-}
-
-#undef IS_SPACE
-
-/*****************************************************************************/
-
-typedef struct {
-	gpointer callback_user_data;
-	GCancellable *cancellable;
-	NMUtilsInvokeOnIdleCallback callback;
-	gulong cancelled_id;
-	guint idle_id;
-} InvokeOnIdleData;
-
-static gboolean
-_nm_utils_invoke_on_idle_cb_idle (gpointer user_data)
-{
-	InvokeOnIdleData *data = user_data;
-
-	data->idle_id = 0;
-	nm_clear_g_signal_handler (data->cancellable, &data->cancelled_id);
-
-	data->callback (data->callback_user_data, data->cancellable);
-	nm_g_object_unref (data->cancellable);
-	g_slice_free (InvokeOnIdleData, data);
-	return G_SOURCE_REMOVE;
-}
-
-static void
-_nm_utils_invoke_on_idle_cb_cancelled (GCancellable *cancellable,
-                                       InvokeOnIdleData *data)
-{
-	/* on cancellation, we invoke the callback synchronously. */
-	nm_clear_g_signal_handler (data->cancellable, &data->cancelled_id);
-	nm_clear_g_source (&data->idle_id);
-	data->callback (data->callback_user_data, data->cancellable);
-	nm_g_object_unref (data->cancellable);
-	g_slice_free (InvokeOnIdleData, data);
-}
-
-void
-nm_utils_invoke_on_idle (NMUtilsInvokeOnIdleCallback callback,
-                         gpointer callback_user_data,
-                         GCancellable *cancellable)
-{
-	InvokeOnIdleData *data;
-
-	g_return_if_fail (callback);
-
-	data = g_slice_new (InvokeOnIdleData);
-	data->callback = callback;
-	data->callback_user_data = callback_user_data;
-	data->cancellable = nm_g_object_ref (cancellable);
-	if (   cancellable
-	    && !g_cancellable_is_cancelled (cancellable)) {
-		/* if we are passed a non-cancelled cancellable, we register to the "cancelled"
-		 * signal an invoke the callback synchronously (from the signal handler).
-		 *
-		 * We don't do that,
-		 *  - if the cancellable is already cancelled (because we don't want to invoke
-		 *    the callback synchronously from the caller).
-		 *  - if we have no cancellable at hand. */
-		data->cancelled_id = g_signal_connect (cancellable,
-		                                       "cancelled",
-		                                       G_CALLBACK (_nm_utils_invoke_on_idle_cb_cancelled),
-		                                       data);
-	} else
-		data->cancelled_id = 0;
-	data->idle_id = g_idle_add (_nm_utils_invoke_on_idle_cb_idle, data);
-}
-
-/*****************************************************************************/
-
-int
-nm_utils_getpagesize (void)
-{
-	static volatile int val = 0;
-	long l;
-	int v;
-
-	v = g_atomic_int_get (&val);
-
-	if (G_UNLIKELY (v == 0)) {
-		l = sysconf (_SC_PAGESIZE);
-
-		g_return_val_if_fail (l > 0 && l < G_MAXINT, 4*1024);
-
-		v = (int) l;
-		if (!g_atomic_int_compare_and_exchange (&val, 0, v)) {
-			v = g_atomic_int_get (&val);
-			g_return_val_if_fail (v > 0, 4*1024);
-		}
-	}
-
-	nm_assert (v > 0);
-#if NM_MORE_ASSERTS > 5
-	nm_assert (v == getpagesize ());
-	nm_assert (v == sysconf (_SC_PAGESIZE));
-#endif
-
-	return v;
-}
-
-gboolean
-nm_utils_memeqzero (gconstpointer data, gsize length)
-{
-	const unsigned char *p = data;
-	int len;
-
-	/* Taken from https://github.com/rustyrussell/ccan/blob/9d2d2c49f053018724bcc6e37029da10b7c3d60d/ccan/mem/mem.c#L92,
-	 * CC-0 licensed. */
-
-	/* Check first 16 bytes manually */
-	for (len = 0; len < 16; len++) {
-		if (!length)
-			return TRUE;
-		if (*p)
-			return FALSE;
-		p++;
-		length--;
-	}
-
-	/* Now we know that's zero, memcmp with self. */
-	return memcmp (data, p, length) == 0;
-}
-
-/**
- * nm_utils_bin2hexstr_full:
- * @addr: pointer of @length bytes. If @length is zero, this may
- *   also be %NULL.
- * @length: number of bytes in @addr. May also be zero, in which
- *   case this will return an empty string.
- * @delimiter: either '\0', otherwise the output string will have the
- *   given delimiter character between each two hex numbers.
- * @upper_case: if TRUE, use upper case ASCII characters for hex.
- * @out: if %NULL, the function will allocate a new buffer of
- *   either (@length*2+1) or (@length*3) bytes, depending on whether
- *   a @delimiter is specified. In that case, the allocated buffer will
- *   be returned and must be freed by the caller.
- *   If not %NULL, the buffer must already be preallocated and contain
- *   at least (@length*2+1) or (@length*3) bytes, depending on the delimiter.
- *
- * Returns: the binary value converted to a hex string. If @out is given,
- *   this always returns @out. If @out is %NULL, a newly allocated string
- *   is returned.
- */
-char *
-nm_utils_bin2hexstr_full (gconstpointer addr,
-                          gsize length,
-                          char delimiter,
-                          gboolean upper_case,
-                          char *out)
-{
-	const guint8 *in = addr;
-	const char *LOOKUP = upper_case ? "0123456789ABCDEF" : "0123456789abcdef";
-	char *out0;
-
-	if (out)
-		out0 = out;
-	else {
-		out0 = out = g_new (char, delimiter == '\0'
-		                          ? length * 2 + 1
-		                          : length * 3);
-	}
-
-	/* @out must contain at least @length*3 bytes if @delimiter is set,
-	 * otherwise, @length*2+1. */
-
-	if (length > 0) {
-		nm_assert (in);
-		for (;;) {
-			const guint8 v = *in++;
-
-			*out++ = LOOKUP[v >> 4];
-			*out++ = LOOKUP[v & 0x0F];
-			length--;
-			if (!length)
-				break;
-			if (delimiter)
-				*out++ = delimiter;
-		}
-	}
-
-	*out = '\0';
-	return out0;
-}
-
-guint8 *
-nm_utils_hexstr2bin_full (const char *hexstr,
-                          gboolean allow_0x_prefix,
-                          gboolean delimiter_required,
-                          const char *delimiter_candidates,
-                          gsize required_len,
-                          guint8 *buffer,
-                          gsize buffer_len,
-                          gsize *out_len)
-{
-	const char *in = hexstr;
-	guint8 *out = buffer;
-	gboolean delimiter_has = TRUE;
-	guint8 delimiter = '\0';
-	gsize len;
-
-	nm_assert (hexstr);
-	nm_assert (buffer);
-	nm_assert (required_len > 0 || out_len);
-
-	if (   allow_0x_prefix
-	    && in[0] == '0'
-	    && in[1] == 'x')
-		in += 2;
-
-	while (TRUE) {
-		const guint8 d1 = in[0];
-		guint8 d2;
-		int i1, i2;
-
-		i1 = nm_utils_hexchar_to_int (d1);
-		if (i1 < 0)
-			goto fail;
-
-		/* If there's no leading zero (ie "aa:b:cc") then fake it */
-		d2 = in[1];
-		if (   d2
-		    && (i2 = nm_utils_hexchar_to_int (d2)) >= 0) {
-			*out++ = (i1 << 4) + i2;
-			d2 = in[2];
-			if (!d2)
-				break;
-			in += 2;
-		} else {
-			/* Fake leading zero */
-			*out++ = i1;
-			if (!d2) {
-				if (!delimiter_has) {
-					/* when using no delimiter, there must be pairs of hex chars */
-					goto fail;
-				}
-				break;
-			}
-			in += 1;
-		}
-
-		if (--buffer_len == 0)
-			goto fail;
-
-		if (delimiter_has) {
-			if (d2 != delimiter) {
-				if (delimiter)
-					goto fail;
-				if (delimiter_candidates) {
-					while (delimiter_candidates[0]) {
-						if (delimiter_candidates++[0] == d2)
-							delimiter = d2;
-					}
-				}
-				if (!delimiter) {
-					if (delimiter_required)
-						goto fail;
-					delimiter_has = FALSE;
-					continue;
-				}
-			}
-			in++;
-		}
-	}
-
-	len = out - buffer;
-	if (   required_len == 0
-	    || len == required_len) {
-		NM_SET_OUT (out_len, len);
-		return buffer;
-	}
-
-fail:
-	NM_SET_OUT (out_len, 0);
-	return NULL;
-}
-
-guint8 *
-nm_utils_hexstr2bin_alloc (const char *hexstr,
-                           gboolean allow_0x_prefix,
-                           gboolean delimiter_required,
-                           const char *delimiter_candidates,
-                           gsize required_len,
-                           gsize *out_len)
-{
-	guint8 *buffer;
-	gsize buffer_len, len;
-
-	g_return_val_if_fail (hexstr, NULL);
-
-	nm_assert (required_len > 0 || out_len);
-
-	if (   allow_0x_prefix
-	    && hexstr[0] == '0'
-	    && hexstr[1] == 'x')
-		hexstr += 2;
-
-	if (!hexstr[0])
-		goto fail;
-
-	if (required_len > 0)
-		buffer_len = required_len;
-	else
-		buffer_len = strlen (hexstr) / 2 + 3;
-
-	buffer = g_malloc (buffer_len);
-
-	if (nm_utils_hexstr2bin_full (hexstr,
-	                              FALSE,
-	                              delimiter_required,
-	                              delimiter_candidates,
-	                              required_len,
-	                              buffer,
-	                              buffer_len,
-	                              &len)) {
-		NM_SET_OUT (out_len, len);
-		return buffer;
-	}
-
-	g_free (buffer);
-
-fail:
-	NM_SET_OUT (out_len, 0);
-	return NULL;
-}
diff --git a/shared/nm-utils/nm-shared-utils.h b/shared/nm-utils/nm-shared-utils.h
deleted file mode 100644
index 65e34959..00000000
--- a/shared/nm-utils/nm-shared-utils.h
+++ /dev/null
@@ -1,1158 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-/* NetworkManager -- Network link manager
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA.
- *
- * (C) Copyright 2016 Red Hat, Inc.
- */
-
-#ifndef __NM_SHARED_UTILS_H__
-#define __NM_SHARED_UTILS_H__
-
-#include <netinet/in.h>
-
-/*****************************************************************************/
-
-pid_t nm_utils_gettid (void);
-
-gboolean _nm_assert_on_main_thread (void);
-
-#if NM_MORE_ASSERTS > 5
-#define NM_ASSERT_ON_MAIN_THREAD() G_STMT_START { nm_assert (_nm_assert_on_main_thread ()); } G_STMT_END
-#else
-#define NM_ASSERT_ON_MAIN_THREAD() G_STMT_START {                                         ; } G_STMT_END
-#endif
-
-/*****************************************************************************/
-
-static inline gboolean
-_NM_INT_NOT_NEGATIVE (gssize val)
-{
-	/* whether an enum (without negative values) is a signed int, depends on compiler options
-	 * and compiler implementation.
-	 *
-	 * When using such an enum for accessing an array, one naturally wants to check
-	 * that the enum is not negative. However, the compiler doesn't like a plain
-	 * comparison "enum_val >= 0", because (if the enum is unsigned), it will warn
-	 * that the expression is always true *duh*. Not even a cast to a signed
-	 * type helps to avoid the compiler warning in any case.
-	 *
-	 * The sole purpose of this function is to avoid a compiler warning, when checking
-	 * that an enum is not negative. */
-	return val >= 0;
-}
-
-/* check whether the integer value is smaller than G_MAXINT32. This macro exists
- * for the sole purpose, that a plain "((int) value <= G_MAXINT32)" comparison
- * may cause the compiler or coverity that this check is always TRUE. But the
- * check depends on compile time and the size of C type "int".  Of course, most
- * of the time in is gint32 and an int value is always <= G_MAXINT32.  The check
- * exists to catch cases where that is not true.
- *
- * Together with the G_STATIC_ASSERT(), we make sure that this is always satisfied. */
-G_STATIC_ASSERT (sizeof (int) == sizeof (gint32));
-#if _NM_CC_SUPPORT_GENERIC
-#define _NM_INT_LE_MAXINT32(value) \
-	({ \
-		_nm_unused typeof (value) _value = (value); \
-		\
-		_Generic((value), \
-		         int: TRUE \
-		); \
-	})
-#else
-#define _NM_INT_LE_MAXINT32(value) ({ \
-		_nm_unused typeof (value) _value = (value); \
-		_nm_unused const int *_p_value = &_value; \
-		\
-		TRUE; \
-	})
-#endif
-
-/*****************************************************************************/
-
-static inline char
-nm_utils_addr_family_to_char (int addr_family)
-{
-	switch (addr_family) {
-	case AF_UNSPEC: return 'X';
-	case AF_INET:   return '4';
-	case AF_INET6:  return '6';
-	}
-	g_return_val_if_reached ('?');
-}
-
-static inline gsize
-nm_utils_addr_family_to_size (int addr_family)
-{
-	switch (addr_family) {
-	case AF_INET:  return sizeof (in_addr_t);
-	case AF_INET6: return sizeof (struct in6_addr);
-	}
-	g_return_val_if_reached (0);
-}
-
-#define nm_assert_addr_family(addr_family) \
-	nm_assert (NM_IN_SET ((addr_family), AF_INET, AF_INET6))
-
-/*****************************************************************************/
-
-typedef struct {
-	union {
-		guint8 addr_ptr[1];
-		in_addr_t addr4;
-		struct in_addr addr4_struct;
-		struct in6_addr addr6;
-
-		/* NMIPAddr is really a union for IP addresses.
-		 * However, as ethernet addresses fit in here nicely, use
-		 * it also for an ethernet MAC address. */
-		guint8 addr_eth[6 /*ETH_ALEN*/];
-	};
-} NMIPAddr;
-
-extern const NMIPAddr nm_ip_addr_zero;
-
-static inline void
-nm_ip_addr_set (int addr_family, gpointer dst, gconstpointer src)
-{
-	nm_assert_addr_family (addr_family);
-	nm_assert (dst);
-	nm_assert (src);
-
-	memcpy (dst,
-	        src,
-	        (addr_family != AF_INET6)
-	          ? sizeof (in_addr_t)
-	          : sizeof (struct in6_addr));
-}
-
-gboolean nm_ip_addr_set_from_untrusted (int addr_family,
-                                        gpointer dst,
-                                        gconstpointer src,
-                                        gsize src_len,
-                                        int *out_addr_family);
-
-static inline gboolean
-nm_ip4_addr_is_localhost (in_addr_t addr4)
-{
-	return (addr4 & htonl (0xFF000000u)) == htonl (0x7F000000u);
-}
-
-/*****************************************************************************/
-
-#define NM_CMP_RETURN(c) \
-    G_STMT_START { \
-        const int _cc = (c); \
-        if (_cc) \
-            return _cc < 0 ? -1 : 1; \
-    } G_STMT_END
-
-#define NM_CMP_SELF(a, b) \
-    G_STMT_START { \
-        typeof (a) _a = (a); \
-        typeof (b) _b = (b); \
-        \
-        if (_a == _b) \
-            return 0; \
-        if (!_a) \
-            return -1; \
-        if (!_b) \
-            return 1; \
-    } G_STMT_END
-
-#define NM_CMP_DIRECT(a, b) \
-    G_STMT_START { \
-        typeof (a) _a = (a); \
-        typeof (b) _b = (b); \
-        \
-        if (_a != _b) \
-            return (_a < _b) ? -1 : 1; \
-    } G_STMT_END
-
-#define NM_CMP_DIRECT_MEMCMP(a, b, size) \
-    NM_CMP_RETURN (memcmp ((a), (b), (size)))
-
-#define NM_CMP_DIRECT_STRCMP0(a, b) \
-    NM_CMP_RETURN (g_strcmp0 ((a), (b)))
-
-#define NM_CMP_DIRECT_IN6ADDR(a, b) \
-    G_STMT_START { \
-        const struct in6_addr *const _a = (a); \
-        const struct in6_addr *const _b = (b); \
-        NM_CMP_RETURN (memcmp (_a, _b, sizeof (struct in6_addr))); \
-    } G_STMT_END
-
-#define NM_CMP_FIELD(a, b, field) \
-    NM_CMP_DIRECT (((a)->field), ((b)->field))
-
-#define NM_CMP_FIELD_UNSAFE(a, b, field) \
-    G_STMT_START { \
-        /* it's unsafe, because it evaluates the arguments more then once.
-         * This is necessary for bitfields, for which typeof() doesn't work. */ \
-        if (((a)->field) != ((b)->field)) \
-            return ((a)->field < ((b)->field)) ? -1 : 1; \
-    } G_STMT_END
-
-#define NM_CMP_FIELD_BOOL(a, b, field) \
-    NM_CMP_DIRECT (!!((a)->field), !!((b)->field))
-
-#define NM_CMP_FIELD_STR(a, b, field) \
-    NM_CMP_RETURN (strcmp (((a)->field), ((b)->field)))
-
-#define NM_CMP_FIELD_STR_INTERNED(a, b, field) \
-    G_STMT_START { \
-        const char *_a = ((a)->field); \
-        const char *_b = ((b)->field); \
-        \
-        if (_a != _b) { \
-            NM_CMP_RETURN (g_strcmp0 (_a, _b)); \
-        } \
-    } G_STMT_END
-
-#define NM_CMP_FIELD_STR0(a, b, field) \
-    NM_CMP_RETURN (g_strcmp0 (((a)->field), ((b)->field)))
-
-#define NM_CMP_FIELD_MEMCMP_LEN(a, b, field, len) \
-    NM_CMP_RETURN (memcmp (&((a)->field), &((b)->field), \
-                           MIN (len, sizeof ((a)->field))))
-
-#define NM_CMP_FIELD_MEMCMP(a, b, field) \
-    NM_CMP_RETURN (memcmp (&((a)->field), \
-                           &((b)->field), \
-                           sizeof ((a)->field)))
-
-#define NM_CMP_FIELD_IN6ADDR(a, b, field) \
-    G_STMT_START { \
-        const struct in6_addr *const _a = &((a)->field); \
-        const struct in6_addr *const _b = &((b)->field); \
-        NM_CMP_RETURN (memcmp (_a, _b, sizeof (struct in6_addr))); \
-    } G_STMT_END
-
-/*****************************************************************************/
-
-gboolean nm_utils_memeqzero (gconstpointer data, gsize length);
-
-/*****************************************************************************/
-
-/* like g_memdup(). The difference is that the @size argument is of type
- * gsize, while g_memdup() has type guint. Since, the size of container types
- * like GArray is guint as well, this means trying to g_memdup() an
- * array,
- *    g_memdup (array->data, array->len * sizeof (ElementType))
- * will lead to integer overflow, if there are more than G_MAXUINT/sizeof(ElementType)
- * bytes. That seems unnecessarily dangerous to me.
- * nm_memdup() avoids that, because its size argument is always large enough
- * to contain all data that a GArray can hold.
- *
- * Another minor difference to g_memdup() is that the glib version also
- * returns %NULL if @data is %NULL. E.g. g_memdup(NULL, 1)
- * gives %NULL, but nm_memdup(NULL, 1) crashes. I think that
- * is desirable, because @size MUST be correct at all times. @size
- * may be zero, but one must not claim to have non-zero bytes when
- * passing a %NULL @data pointer.
- */
-static inline gpointer
-nm_memdup (gconstpointer data, gsize size)
-{
-	gpointer p;
-
-	if (size == 0)
-		return NULL;
-	p = g_malloc (size);
-	memcpy (p, data, size);
-	return p;
-}
-
-static inline char *
-_nm_strndup_a_step (char *s, const char *str, gsize len)
-{
-	NM_PRAGMA_WARNING_DISABLE ("-Wstringop-truncation");
-	if (len > 0)
-		strncpy (s, str, len);
-	s[len] = '\0';
-	return s;
-	NM_PRAGMA_WARNING_REENABLE;
-}
-
-/* Similar to g_strndup(), however, if the string (including the terminating
- * NUL char) fits into alloca_maxlen, this will alloca() the memory.
- *
- * It's a mix of strndup() and strndupa(), but deciding based on @alloca_maxlen
- * which one to use.
- *
- * In case malloc() is necessary, @out_str_free will be set (this string
- * must be freed afterwards). It is permissible to pass %NULL as @out_str_free,
- * if you ensure that len < alloca_maxlen.
- *
- * Note that just like g_strndup(), this always returns a buffer with @len + 1
- * bytes, even if strlen(@str) is shorter than that (NUL terminated early). We fill
- * the buffer with strncpy(), which means, that @str is copied up to the first
- * NUL character and then filled with NUL characters. */
-#define nm_strndup_a(alloca_maxlen, str, len, out_str_free) \
-	({ \
-		const gsize _alloca_maxlen = (alloca_maxlen); \
-		const char *const _str = (str); \
-		const gsize _len = (len); \
-		char **const _out_str_free = (out_str_free); \
-		char *_s; \
-		\
-		G_STATIC_ASSERT_EXPR ((alloca_maxlen) <= 300); \
-		\
-		if (   _out_str_free \
-		    && _len >= _alloca_maxlen) { \
-			_s = g_malloc (_len + 1); \
-			*_out_str_free = _s; \
-		} else { \
-			g_assert (_len < _alloca_maxlen); \
-			_s = g_alloca (_len + 1); \
-		} \
-		_nm_strndup_a_step (_s, _str, _len); \
-	})
-
-/*****************************************************************************/
-
-/* generic macro to convert an int to a (heap allocated) string.
- *
- * Usually, an inline function nm_strdup_int64() would be enough. However,
- * that cannot be used for guint64. So, we would also need nm_strdup_uint64().
- * This causes subtle error potential, because the caller needs to ensure to
- * use the right one (and compiler isn't going to help as it silently casts).
- *
- * Instead, this generic macro is supposed to handle all integers correctly. */
-#if _NM_CC_SUPPORT_GENERIC
-#define nm_strdup_int(val) \
-	_Generic ((val), \
-	          char:               g_strdup_printf ("%d",   (int)                (val)), \
-	          \
-	          signed char:        g_strdup_printf ("%d",   (signed)             (val)), \
-	          signed short:       g_strdup_printf ("%d",   (signed)             (val)), \
-	          signed:             g_strdup_printf ("%d",   (signed)             (val)), \
-	          signed long:        g_strdup_printf ("%ld",  (signed long)        (val)), \
-	          signed long long:   g_strdup_printf ("%lld", (signed long long)   (val)), \
-	          \
-	          unsigned char:      g_strdup_printf ("%u",   (unsigned)           (val)), \
-	          unsigned short:     g_strdup_printf ("%u",   (unsigned)           (val)), \
-	          unsigned:           g_strdup_printf ("%u",   (unsigned)           (val)), \
-	          unsigned long:      g_strdup_printf ("%lu",  (unsigned long)      (val)), \
-	          unsigned long long: g_strdup_printf ("%llu", (unsigned long long) (val))  \
-	)
-#else
-#define nm_strdup_int(val) \
-	(  (   sizeof (val) == sizeof (guint64) \
-	    && ((typeof (val)) -1) > 0) \
-	 ? g_strdup_printf ("%"G_GUINT64_FORMAT, (guint64) (val)) \
-	 : g_strdup_printf ("%"G_GINT64_FORMAT, (gint64) (val)))
-#endif
-
-/*****************************************************************************/
-
-extern const void *const _NM_PTRARRAY_EMPTY[1];
-
-#define NM_PTRARRAY_EMPTY(type) ((type const*) _NM_PTRARRAY_EMPTY)
-
-static inline void
-_nm_utils_strbuf_init (char *buf, gsize len, char **p_buf_ptr, gsize *p_buf_len)
-{
-	NM_SET_OUT (p_buf_len, len);
-	NM_SET_OUT (p_buf_ptr, buf);
-	buf[0] = '\0';
-}
-
-#define nm_utils_strbuf_init(buf, p_buf_ptr, p_buf_len) \
-	G_STMT_START { \
-		G_STATIC_ASSERT (G_N_ELEMENTS (buf) == sizeof (buf) && sizeof (buf) > sizeof (char *)); \
-		_nm_utils_strbuf_init ((buf), sizeof (buf), (p_buf_ptr), (p_buf_len)); \
-	} G_STMT_END
-void nm_utils_strbuf_append (char **buf, gsize *len, const char *format, ...) _nm_printf (3, 4);
-void nm_utils_strbuf_append_c (char **buf, gsize *len, char c);
-void nm_utils_strbuf_append_str (char **buf, gsize *len, const char *str);
-void nm_utils_strbuf_append_bin (char **buf, gsize *len, gconstpointer str, gsize str_len);
-void nm_utils_strbuf_seek_end (char **buf, gsize *len);
-
-const char *nm_strquote (char *buf, gsize buf_len, const char *str);
-
-static inline gboolean
-nm_utils_is_separator (const char c)
-{
-	return NM_IN_SET (c, ' ', '\t');
-}
-
-/*****************************************************************************/
-
-static inline gboolean
-nm_gbytes_equal0 (GBytes *a, GBytes *b)
-{
-	return a == b || (a && b && g_bytes_equal (a, b));
-}
-
-gboolean nm_utils_gbytes_equal_mem (GBytes *bytes,
-                                    gconstpointer mem_data,
-                                    gsize mem_len);
-
-GVariant *nm_utils_gbytes_to_variant_ay (GBytes *bytes);
-
-/*****************************************************************************/
-
-static inline int
-nm_utils_hexchar_to_int (char ch)
-{
-	G_STATIC_ASSERT_EXPR ('0' < 'A');
-	G_STATIC_ASSERT_EXPR ('A' < 'a');
-
-	if (ch >= '0') {
-		if (ch <= '9')
-			return ch - '0';
-		if (ch >= 'A') {
-			if (ch <= 'F')
-				return ((int) ch) + (10 - (int) 'A');
-			if (ch >= 'a' && ch <= 'f')
-				return ((int) ch) + (10 - (int) 'a');
-		}
-	}
-	return -1;
-}
-
-/*****************************************************************************/
-
-const char *nm_utils_dbus_path_get_last_component (const char *dbus_path);
-
-int nm_utils_dbus_path_cmp (const char *dbus_path_a, const char *dbus_path_b);
-
-/*****************************************************************************/
-
-const char **nm_utils_strsplit_set (const char *str, const char *delimiters, gboolean allow_escaping);
-
-gssize nm_utils_strv_find_first (char **list, gssize len, const char *needle);
-
-char **_nm_utils_strv_cleanup (char **strv,
-                               gboolean strip_whitespace,
-                               gboolean skip_empty,
-                               gboolean skip_repeated);
-
-/*****************************************************************************/
-
-#define NM_UTILS_CHECKSUM_LENGTH_MD5          16
-#define NM_UTILS_CHECKSUM_LENGTH_SHA1         20
-#define NM_UTILS_CHECKSUM_LENGTH_SHA256       32
-
-#define nm_utils_checksum_get_digest(sum, arr) \
-	G_STMT_START { \
-		GChecksum *const _sum = (sum); \
-		gsize _len; \
-		\
-		G_STATIC_ASSERT_EXPR (   sizeof (arr) == NM_UTILS_CHECKSUM_LENGTH_MD5 \
-		                      || sizeof (arr) == NM_UTILS_CHECKSUM_LENGTH_SHA1 \
-		                      || sizeof (arr) == NM_UTILS_CHECKSUM_LENGTH_SHA256); \
-		G_STATIC_ASSERT_EXPR (sizeof (arr) == G_N_ELEMENTS (arr)); \
-		\
-		nm_assert (_sum); \
-		\
-		_len = G_N_ELEMENTS (arr); \
-		\
-		g_checksum_get_digest (_sum, (arr), &_len); \
-		nm_assert (_len == G_N_ELEMENTS (arr)); \
-	} G_STMT_END
-
-#define nm_utils_checksum_get_digest_len(sum, buf, len) \
-	G_STMT_START { \
-		GChecksum *const _sum = (sum); \
-		const gsize _len0 = (len); \
-		gsize _len; \
-		\
-		nm_assert (NM_IN_SET (_len0, NM_UTILS_CHECKSUM_LENGTH_MD5, \
-		                             NM_UTILS_CHECKSUM_LENGTH_SHA1, \
-		                             NM_UTILS_CHECKSUM_LENGTH_SHA256)); \
-		nm_assert (_sum); \
-		\
-		_len = _len0; \
-		g_checksum_get_digest (_sum, (buf), &_len); \
-		nm_assert (_len == _len0); \
-	} G_STMT_END
-
-/*****************************************************************************/
-
-guint32 _nm_utils_ip4_prefix_to_netmask (guint32 prefix);
-guint32 _nm_utils_ip4_get_default_prefix (guint32 ip);
-
-gboolean nm_utils_ip_is_site_local (int addr_family,
-                                    const void *address);
-
-/*****************************************************************************/
-
-gboolean nm_utils_parse_inaddr_bin  (int addr_family,
-                                     const char *text,
-                                     int *out_addr_family,
-                                     gpointer out_addr);
-
-gboolean nm_utils_parse_inaddr (int addr_family,
-                                const char *text,
-                                char **out_addr);
-
-gboolean nm_utils_parse_inaddr_prefix_bin (int addr_family,
-                                           const char *text,
-                                           int *out_addr_family,
-                                           gpointer out_addr,
-                                           int *out_prefix);
-
-gboolean nm_utils_parse_inaddr_prefix (int addr_family,
-                                       const char *text,
-                                       char **out_addr,
-                                       int *out_prefix);
-
-gint64  _nm_utils_ascii_str_to_int64  (const char *str, guint base, gint64  min, gint64  max, gint64  fallback);
-guint64 _nm_utils_ascii_str_to_uint64 (const char *str, guint base, guint64 min, guint64 max, guint64 fallback);
-
-int _nm_utils_ascii_str_to_bool (const char *str,
-                                  int default_value);
-
-/*****************************************************************************/
-
-extern char _nm_utils_to_string_buffer[2096];
-
-void     nm_utils_to_string_buffer_init (char **buf, gsize *len);
-gboolean nm_utils_to_string_buffer_init_null (gconstpointer obj, char **buf, gsize *len);
-
-/*****************************************************************************/
-
-typedef struct {
-	unsigned flag;
-	const char *name;
-} NMUtilsFlags2StrDesc;
-
-#define NM_UTILS_FLAGS2STR(f, n) { .flag = f, .name = ""n, }
-
-#define _NM_UTILS_FLAGS2STR_DEFINE(scope, fcn_name, flags_type, ...) \
-scope const char * \
-fcn_name (flags_type flags, char *buf, gsize len) \
-{ \
-	static const NMUtilsFlags2StrDesc descs[] = { \
-		__VA_ARGS__ \
-	}; \
-	G_STATIC_ASSERT (sizeof (flags_type) <= sizeof (unsigned)); \
-	return nm_utils_flags2str (descs, G_N_ELEMENTS (descs), flags, buf, len); \
-};
-
-#define NM_UTILS_FLAGS2STR_DEFINE(fcn_name, flags_type, ...) \
-	_NM_UTILS_FLAGS2STR_DEFINE (, fcn_name, flags_type, __VA_ARGS__)
-#define NM_UTILS_FLAGS2STR_DEFINE_STATIC(fcn_name, flags_type, ...) \
-	_NM_UTILS_FLAGS2STR_DEFINE (static, fcn_name, flags_type, __VA_ARGS__)
-
-const char *nm_utils_flags2str (const NMUtilsFlags2StrDesc *descs,
-                                gsize n_descs,
-                                unsigned flags,
-                                char *buf,
-                                gsize len);
-
-/*****************************************************************************/
-
-#define NM_UTILS_ENUM2STR(v, n)     (void) 0; case v: s = ""n""; break; (void) 0
-#define NM_UTILS_ENUM2STR_IGNORE(v) (void) 0; case v: break; (void) 0
-
-#define _NM_UTILS_ENUM2STR_DEFINE(scope, fcn_name, lookup_type, int_fmt, ...) \
-scope const char * \
-fcn_name (lookup_type val, char *buf, gsize len) \
-{ \
-	nm_utils_to_string_buffer_init (&buf, &len); \
-	if (len) { \
-		const char *s = NULL; \
-		switch (val) { \
-			(void) 0, \
-			__VA_ARGS__ \
-			(void) 0; \
-		}; \
-		if (s) \
-			g_strlcpy (buf, s, len); \
-		else \
-			g_snprintf (buf, len, "(%"int_fmt")", val); \
-	} \
-	return buf; \
-}
-
-#define NM_UTILS_ENUM2STR_DEFINE(fcn_name, lookup_type, ...) \
-	_NM_UTILS_ENUM2STR_DEFINE (, fcn_name, lookup_type, "d", __VA_ARGS__)
-#define NM_UTILS_ENUM2STR_DEFINE_STATIC(fcn_name, lookup_type, ...) \
-	_NM_UTILS_ENUM2STR_DEFINE (static, fcn_name, lookup_type, "d", __VA_ARGS__)
-
-/*****************************************************************************/
-
-#define _nm_g_slice_free_fcn_define(mem_size) \
-static inline void \
-_nm_g_slice_free_fcn_##mem_size (gpointer mem_block) \
-{ \
-	g_slice_free1 (mem_size, mem_block); \
-}
-
-_nm_g_slice_free_fcn_define (1)
-_nm_g_slice_free_fcn_define (2)
-_nm_g_slice_free_fcn_define (4)
-_nm_g_slice_free_fcn_define (8)
-_nm_g_slice_free_fcn_define (10)
-_nm_g_slice_free_fcn_define (12)
-_nm_g_slice_free_fcn_define (16)
-
-#define _nm_g_slice_free_fcn1(mem_size) \
-	({ \
-		void (*_fcn) (gpointer); \
-		\
-		/* If mem_size is a compile time constant, the compiler
-		 * will be able to optimize this. Hence, you don't want
-		 * to call this with a non-constant size argument. */ \
-		G_STATIC_ASSERT_EXPR (   ((mem_size) ==  1) \
-		                      || ((mem_size) ==  2) \
-		                      || ((mem_size) ==  4) \
-		                      || ((mem_size) ==  8) \
-		                      || ((mem_size) == 10) \
-		                      || ((mem_size) == 12) \
-		                      || ((mem_size) == 16)); \
-		switch ((mem_size)) { \
-		case  1: _fcn = _nm_g_slice_free_fcn_1;  break; \
-		case  2: _fcn = _nm_g_slice_free_fcn_2;  break; \
-		case  4: _fcn = _nm_g_slice_free_fcn_4;  break; \
-		case  8: _fcn = _nm_g_slice_free_fcn_8;  break; \
-		case 10: _fcn = _nm_g_slice_free_fcn_10; break; \
-		case 12: _fcn = _nm_g_slice_free_fcn_12; break; \
-		case 16: _fcn = _nm_g_slice_free_fcn_16; break; \
-		default: g_assert_not_reached (); _fcn = NULL; break; \
-		} \
-		_fcn; \
-	})
-
-/**
- * nm_g_slice_free_fcn:
- * @type: type argument for sizeof() operator that you would
- *   pass to g_slice_new().
- *
- * Returns: a function pointer with GDestroyNotify signature
- *   for g_slice_free(type,*).
- *
- * Only certain types are implemented. You'll get an assertion
- * using the wrong type. */
-#define nm_g_slice_free_fcn(type) (_nm_g_slice_free_fcn1 (sizeof (type)))
-
-#define nm_g_slice_free_fcn_gint64 (nm_g_slice_free_fcn (gint64))
-
-/*****************************************************************************/
-
-/**
- * NMUtilsError:
- * @NM_UTILS_ERROR_UNKNOWN: unknown or unclassified error
- * @NM_UTILS_ERROR_CANCELLED_DISPOSING: when disposing an object that has
- *   pending aynchronous operations, the operation is cancelled with this
- *   error reason. Depending on the usage, this might indicate a bug because
- *   usually the target object should stay alive as long as there are pending
- *   operations.
- *
- * @NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE: used for a very particular
- *   purpose during nm_device_check_connection_compatible() to indicate that
- *   the profile does not match the device already because their type differs.
- *   That is, there is a fundamental reason of trying to check a profile that
- *   cannot possibly match on this device.
- * @NM_UTILS_ERROR_CONNECTION_AVAILABLE_UNMANAGED_DEVICE: used for a very particular
- *   purpose during nm_device_check_connection_available(), to indicate that the
- *   device is not available because it is unmanaged.
- * @NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY: the profile is currently not
- *   available/compatible with the device, but this may be only temporary.
- *
- * @NM_UTILS_ERROR_INVALID_ARGUMENT: invalid argument.
- */
-typedef enum {
-	NM_UTILS_ERROR_UNKNOWN = 0,                 /*< nick=Unknown >*/
-	NM_UTILS_ERROR_CANCELLED_DISPOSING,         /*< nick=CancelledDisposing >*/
-	NM_UTILS_ERROR_INVALID_ARGUMENT,            /*< nick=InvalidArgument >*/
-
-	/* the following codes have a special meaning and are exactly used for
-	 * nm_device_check_connection_compatible() and nm_device_check_connection_available().
-	 *
-	 * Actually, their meaning is not very important (so, don't think too
-	 * hard about the name of these error codes). What is important, is their
-	 * relative order (i.e. the integer value of the codes). When manager
-	 * searches for a suitable device, it will check all devices whether
-	 * a profile can be activated. If they all fail, it will pick the error
-	 * message from the device that returned the *highest* error code,
-	 * in the hope that this message makes the most sense for the caller.
-	 * */
-	NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE,
-	NM_UTILS_ERROR_CONNECTION_AVAILABLE_UNMANAGED_DEVICE,
-	NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
-
-} NMUtilsError;
-
-#define NM_UTILS_ERROR (nm_utils_error_quark ())
-GQuark nm_utils_error_quark (void);
-
-void nm_utils_error_set_cancelled (GError **error,
-                                   gboolean is_disposing,
-                                   const char *instance_name);
-gboolean nm_utils_error_is_cancelled (GError *error,
-                                      gboolean consider_is_disposing);
-
-gboolean nm_utils_error_is_notfound (GError *error);
-
-static inline void
-nm_utils_error_set_literal (GError **error, int error_code, const char *literal)
-{
-	g_set_error_literal (error, NM_UTILS_ERROR, error_code, literal);
-}
-
-#define nm_utils_error_set(error, error_code, ...) \
-	g_set_error ((error), NM_UTILS_ERROR, error_code, __VA_ARGS__)
-
-#define nm_utils_error_set_errno(error, errsv, fmt, ...) \
-	G_STMT_START { \
-		char _bstrerr[NM_STRERROR_BUFSIZE]; \
-		\
-		g_set_error ((error), \
-		             NM_UTILS_ERROR, \
-		             NM_UTILS_ERROR_UNKNOWN, \
-		             fmt, \
-		             ##__VA_ARGS__, \
-		             nm_strerror_native_r (({ \
-		                                      const int _errsv = (errsv); \
-		                                      \
-		                                      (  _errsv >= 0 \
-		                                       ? _errsv \
-		                                       : (  G_UNLIKELY (_errsv == G_MININT) \
-		                                          ? G_MAXINT \
-		                                          : -errsv)); \
-		                                   }), \
-		                                   _bstrerr, \
-		                                   sizeof (_bstrerr))); \
-	} G_STMT_END
-
-/*****************************************************************************/
-
-gboolean nm_g_object_set_property (GObject *object,
-                                   const char *property_name,
-                                   const GValue *value,
-                                   GError **error);
-
-gboolean nm_g_object_set_property_string (GObject *object,
-                                          const char *property_name,
-                                          const char *value,
-                                          GError **error);
-
-gboolean nm_g_object_set_property_string_static (GObject *object,
-                                                 const char *property_name,
-                                                 const char *value,
-                                                 GError **error);
-
-gboolean nm_g_object_set_property_string_take (GObject *object,
-                                               const char *property_name,
-                                               char *value,
-                                               GError **error);
-
-gboolean nm_g_object_set_property_boolean (GObject *object,
-                                           const char *property_name,
-                                           gboolean value,
-                                           GError **error);
-
-gboolean nm_g_object_set_property_char (GObject *object,
-                                        const char *property_name,
-                                        gint8 value,
-                                        GError **error);
-
-gboolean nm_g_object_set_property_uchar (GObject *object,
-                                         const char *property_name,
-                                         guint8 value,
-                                         GError **error);
-
-gboolean nm_g_object_set_property_int (GObject *object,
-                                       const char *property_name,
-                                       int value,
-                                       GError **error);
-
-gboolean nm_g_object_set_property_int64 (GObject *object,
-                                         const char *property_name,
-                                         gint64 value,
-                                         GError **error);
-
-gboolean nm_g_object_set_property_uint (GObject *object,
-                                        const char *property_name,
-                                        guint value,
-                                        GError **error);
-
-gboolean nm_g_object_set_property_uint64 (GObject *object,
-                                          const char *property_name,
-                                          guint64 value,
-                                          GError **error);
-
-gboolean nm_g_object_set_property_flags (GObject *object,
-                                         const char *property_name,
-                                         GType gtype,
-                                         guint value,
-                                         GError **error);
-
-gboolean nm_g_object_set_property_enum (GObject *object,
-                                        const char *property_name,
-                                        GType gtype,
-                                        int value,
-                                        GError **error);
-
-GParamSpec *nm_g_object_class_find_property_from_gtype (GType gtype,
-                                                        const char *property_name);
-
-/*****************************************************************************/
-
-GType nm_g_type_find_implementing_class_for_property (GType gtype,
-                                                      const char *pname);
-
-/*****************************************************************************/
-
-typedef enum {
-	NM_UTILS_STR_UTF8_SAFE_FLAG_NONE                = 0,
-	NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL         = 0x0001,
-	NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_NON_ASCII    = 0x0002,
-} NMUtilsStrUtf8SafeFlags;
-
-const char *nm_utils_buf_utf8safe_escape (gconstpointer buf, gssize buflen, NMUtilsStrUtf8SafeFlags flags, char **to_free);
-const char *nm_utils_buf_utf8safe_escape_bytes (GBytes *bytes, NMUtilsStrUtf8SafeFlags flags, char **to_free);
-gconstpointer nm_utils_buf_utf8safe_unescape (const char *str, gsize *out_len, gpointer *to_free);
-
-const char *nm_utils_str_utf8safe_escape   (const char *str, NMUtilsStrUtf8SafeFlags flags, char **to_free);
-const char *nm_utils_str_utf8safe_unescape (const char *str, char **to_free);
-
-char *nm_utils_str_utf8safe_escape_cp   (const char *str, NMUtilsStrUtf8SafeFlags flags);
-char *nm_utils_str_utf8safe_unescape_cp (const char *str);
-
-char *nm_utils_str_utf8safe_escape_take (char *str, NMUtilsStrUtf8SafeFlags flags);
-
-static inline void
-nm_g_variant_unref_floating (GVariant *var)
-{
-	/* often a function wants to keep a reference to an input variant.
-	 * It uses g_variant_ref_sink() to either increase the ref-count,
-	 * or take ownership of a possibly floating reference.
-	 *
-	 * If the function doesn't actually want to do anything with the
-	 * input variant, it still must make sure that a passed in floating
-	 * reference is consumed. Hence, this helper which:
-	 *
-	 *   - does nothing if @var is not floating
-	 *   - unrefs (consumes) @var if it is floating. */
-	if (g_variant_is_floating (var))
-		g_variant_unref (var);
-}
-
-/*****************************************************************************/
-
-static inline int
-nm_utf8_collate0 (const char *a, const char *b)
-{
-	if (!a)
-		return !b ? 0 : -1;
-	if (!b)
-		return 1;
-	return g_utf8_collate (a, b);
-}
-
-int nm_strcmp_p_with_data (gconstpointer a, gconstpointer b, gpointer user_data);
-int nm_cmp_uint32_p_with_data (gconstpointer p_a, gconstpointer p_b, gpointer user_data);
-int nm_cmp_int2ptr_p_with_data (gconstpointer p_a, gconstpointer p_b, gpointer user_data);
-
-/*****************************************************************************/
-
-typedef struct {
-	const char *name;
-} NMUtilsNamedEntry;
-
-typedef struct {
-	union {
-		NMUtilsNamedEntry named_entry;
-		const char *name;
-	};
-	union {
-		const char *value_str;
-		gconstpointer value_ptr;
-	};
-} NMUtilsNamedValue;
-
-#define nm_utils_named_entry_cmp           nm_strcmp_p
-#define nm_utils_named_entry_cmp_with_data nm_strcmp_p_with_data
-
-NMUtilsNamedValue *nm_utils_named_values_from_str_dict (GHashTable *hash, guint *out_len);
-
-gpointer *nm_utils_hash_keys_to_array (GHashTable *hash,
-                                       GCompareDataFunc compare_func,
-                                       gpointer user_data,
-                                       guint *out_len);
-
-static inline const char **
-nm_utils_strdict_get_keys (const GHashTable *hash,
-                           gboolean sorted,
-                           guint *out_length)
-{
-	return (const char **) nm_utils_hash_keys_to_array ((GHashTable *) hash,
-	                                                    sorted ? nm_strcmp_p_with_data : NULL,
-	                                                    NULL,
-	                                                    out_length);
-}
-
-char **nm_utils_strv_make_deep_copied (const char **strv);
-
-static inline char **
-nm_utils_strv_make_deep_copied_nonnull (const char **strv)
-{
-	return nm_utils_strv_make_deep_copied (strv) ?: g_new0 (char *, 1);
-}
-
-/*****************************************************************************/
-
-gssize nm_utils_ptrarray_find_binary_search (gconstpointer *list,
-                                             gsize len,
-                                             gconstpointer needle,
-                                             GCompareDataFunc cmpfcn,
-                                             gpointer user_data,
-                                             gssize *out_idx_first,
-                                             gssize *out_idx_last);
-
-gssize nm_utils_array_find_binary_search (gconstpointer list,
-                                          gsize elem_size,
-                                          gsize len,
-                                          gconstpointer needle,
-                                          GCompareDataFunc cmpfcn,
-                                          gpointer user_data);
-
-/*****************************************************************************/
-
-typedef gboolean (*NMUtilsHashTableEqualFunc) (gconstpointer a,
-                                               gconstpointer b);
-
-gboolean nm_utils_hash_table_equal (const GHashTable *a,
-                                    const GHashTable *b,
-                                    gboolean treat_null_as_empty,
-                                    NMUtilsHashTableEqualFunc equal_func);
-
-/*****************************************************************************/
-
-void _nm_utils_strv_sort (const char **strv, gssize len);
-#define nm_utils_strv_sort(strv, len) _nm_utils_strv_sort (NM_CAST_STRV_MC (strv), len)
-
-/*****************************************************************************/
-
-#define NM_UTILS_NS_PER_SECOND   ((gint64) 1000000000)
-#define NM_UTILS_NS_PER_MSEC     ((gint64) 1000000)
-#define NM_UTILS_MSEC_PER_SECOND ((gint64) 1000)
-#define NM_UTILS_NS_TO_MSEC_CEIL(nsec)      (((nsec) + (NM_UTILS_NS_PER_MSEC - 1)) / NM_UTILS_NS_PER_MSEC)
-
-/*****************************************************************************/
-
-int nm_utils_fd_wait_for_event (int fd, int event, gint64 timeout_ns);
-ssize_t nm_utils_fd_read_loop (int fd, void *buf, size_t nbytes, bool do_poll);
-int nm_utils_fd_read_loop_exact (int fd, void *buf, size_t nbytes, bool do_poll);
-
-/*****************************************************************************/
-
-static inline const char *
-nm_utils_dbus_normalize_object_path (const char *path)
-{
-	/* D-Bus does not allow an empty object path. Hence, whenever we mean NULL / no-object
-	 * on D-Bus, it's path is actually "/".
-	 *
-	 * Normalize that away, and return %NULL in that case. */
-	if (path && path[0] == '/' && path[1] == '\0')
-		return NULL;
-	return path;
-}
-
-#define NM_DEFINE_GDBUS_ARG_INFO_FULL(name_, ...) \
-	((GDBusArgInfo *) (&((const GDBusArgInfo) { \
-		.ref_count = -1, \
-		.name = name_, \
-		__VA_ARGS__ \
-	})))
-
-#define NM_DEFINE_GDBUS_ARG_INFO(name_, a_signature) \
-	NM_DEFINE_GDBUS_ARG_INFO_FULL ( \
-		name_, \
-		.signature = a_signature, \
-	)
-
-#define NM_DEFINE_GDBUS_ARG_INFOS(...) \
-	((GDBusArgInfo **) ((const GDBusArgInfo *[]) { \
-		__VA_ARGS__ \
-		NULL, \
-	}))
-
-#define NM_DEFINE_GDBUS_PROPERTY_INFO(name_, ...) \
-	((GDBusPropertyInfo *) (&((const GDBusPropertyInfo) { \
-		.ref_count = -1, \
-		.name = name_, \
-		__VA_ARGS__ \
-	})))
-
-#define NM_DEFINE_GDBUS_PROPERTY_INFO_READABLE(name_, m_signature) \
-	NM_DEFINE_GDBUS_PROPERTY_INFO ( \
-		name_, \
-		.signature = m_signature, \
-		.flags = G_DBUS_PROPERTY_INFO_FLAGS_READABLE, \
-	)
-
-#define NM_DEFINE_GDBUS_PROPERTY_INFOS(...) \
-	((GDBusPropertyInfo **) ((const GDBusPropertyInfo *[]) { \
-		__VA_ARGS__ \
-		NULL, \
-	}))
-
-#define NM_DEFINE_GDBUS_SIGNAL_INFO_INIT(name_, ...) \
-	{ \
-		.ref_count = -1, \
-		.name = name_, \
-		__VA_ARGS__ \
-	}
-
-#define NM_DEFINE_GDBUS_SIGNAL_INFO(name_, ...) \
-	((GDBusSignalInfo *) (&((const GDBusSignalInfo) NM_DEFINE_GDBUS_SIGNAL_INFO_INIT (name_, __VA_ARGS__))))
-
-#define NM_DEFINE_GDBUS_SIGNAL_INFOS(...) \
-	((GDBusSignalInfo **) ((const GDBusSignalInfo *[]) { \
-		__VA_ARGS__ \
-		NULL, \
-	}))
-
-#define NM_DEFINE_GDBUS_METHOD_INFO_INIT(name_, ...) \
-	{ \
-		.ref_count = -1, \
-		.name = name_, \
-		__VA_ARGS__ \
-	}
-
-#define NM_DEFINE_GDBUS_METHOD_INFO(name_, ...) \
-	((GDBusMethodInfo *) (&((const GDBusMethodInfo) NM_DEFINE_GDBUS_METHOD_INFO_INIT (name_, __VA_ARGS__))))
-
-#define NM_DEFINE_GDBUS_METHOD_INFOS(...) \
-	((GDBusMethodInfo **) ((const GDBusMethodInfo *[]) { \
-		__VA_ARGS__ \
-		NULL, \
-	}))
-
-#define NM_DEFINE_GDBUS_INTERFACE_INFO_INIT(name_, ...) \
-	{ \
-		.ref_count = -1, \
-		.name = name_, \
-		__VA_ARGS__ \
-	}
-
-#define NM_DEFINE_GDBUS_INTERFACE_INFO(name_, ...) \
-	((GDBusInterfaceInfo *) (&((const GDBusInterfaceInfo) NM_DEFINE_GDBUS_INTERFACE_INFO_INIT (name_, __VA_ARGS__))))
-
-#define NM_DEFINE_GDBUS_INTERFACE_VTABLE(...) \
-	((GDBusInterfaceVTable *) (&((const GDBusInterfaceVTable) { \
-		__VA_ARGS__ \
-	})))
-
-/*****************************************************************************/
-
-guint64 nm_utils_get_start_time_for_pid (pid_t pid, char *out_state, pid_t *out_ppid);
-
-/*****************************************************************************/
-
-gpointer _nm_utils_user_data_pack (int nargs, gconstpointer *args);
-
-#define nm_utils_user_data_pack(...) \
-	_nm_utils_user_data_pack(NM_NARG (__VA_ARGS__), (gconstpointer[]) { __VA_ARGS__ })
-
-void _nm_utils_user_data_unpack (gpointer user_data, int nargs, ...);
-
-#define nm_utils_user_data_unpack(user_data, ...) \
-	_nm_utils_user_data_unpack(user_data, NM_NARG (__VA_ARGS__), __VA_ARGS__)
-
-/*****************************************************************************/
-
-const char *_nm_utils_escape_spaces (const char *str, char **to_free);
-char *_nm_utils_unescape_spaces (char *str);
-
-/*****************************************************************************/
-
-typedef void (*NMUtilsInvokeOnIdleCallback) (gpointer callback_user_data,
-                                             GCancellable *cancellable);
-
-void nm_utils_invoke_on_idle (NMUtilsInvokeOnIdleCallback callback,
-                              gpointer callback_user_data,
-                              GCancellable *cancellable);
-
-/*****************************************************************************/
-
-static inline void
-nm_strv_ptrarray_add_string_take (GPtrArray *cmd,
-                                  char *str)
-{
-	nm_assert (cmd);
-	nm_assert (str);
-
-	g_ptr_array_add (cmd, str);
-}
-
-static inline void
-nm_strv_ptrarray_add_string_dup (GPtrArray *cmd,
-                                 const char *str)
-{
-	nm_strv_ptrarray_add_string_take (cmd,
-	                                  g_strdup (str));
-}
-
-#define nm_strv_ptrarray_add_string_concat(cmd, ...) \
-	nm_strv_ptrarray_add_string_take ((cmd), g_strconcat (__VA_ARGS__, NULL))
-
-#define nm_strv_ptrarray_add_string_printf(cmd, ...) \
-	nm_strv_ptrarray_add_string_take ((cmd), g_strdup_printf (__VA_ARGS__))
-
-#define nm_strv_ptrarray_add_int(cmd, val) \
-	nm_strv_ptrarray_add_string_take ((cmd), nm_strdup_int (val))
-
-static inline void
-nm_strv_ptrarray_take_gstring (GPtrArray *cmd,
-                               GString **gstr)
-{
-	nm_assert (gstr && *gstr);
-
-	nm_strv_ptrarray_add_string_take (cmd,
-	                                  g_string_free (g_steal_pointer (gstr),
-	                                                 FALSE));
-}
-
-/*****************************************************************************/
-
-int nm_utils_getpagesize (void);
-
-/*****************************************************************************/
-
-char *nm_utils_bin2hexstr_full (gconstpointer addr,
-                                gsize length,
-                                char delimiter,
-                                gboolean upper_case,
-                                char *out);
-
-guint8 *nm_utils_hexstr2bin_full (const char *hexstr,
-                                  gboolean allow_0x_prefix,
-                                  gboolean delimiter_required,
-                                  const char *delimiter_candidates,
-                                  gsize required_len,
-                                  guint8 *buffer,
-                                  gsize buffer_len,
-                                  gsize *out_len);
-
-#define nm_utils_hexstr2bin_buf(hexstr, allow_0x_prefix, delimiter_required, delimiter_candidates, buffer) \
-    nm_utils_hexstr2bin_full ((hexstr), (allow_0x_prefix), (delimiter_required), (delimiter_candidates), G_N_ELEMENTS (buffer), (buffer), G_N_ELEMENTS (buffer), NULL)
-
-guint8 *nm_utils_hexstr2bin_alloc (const char *hexstr,
-                                   gboolean allow_0x_prefix,
-                                   gboolean delimiter_required,
-                                   const char *delimiter_candidates,
-                                   gsize required_len,
-                                   gsize *out_len);
-
-#endif /* __NM_SHARED_UTILS_H__ */
diff --git a/shared/nm-utils/nm-test-utils.h b/shared/nm-utils/nm-test-utils.h
index c5ea5e3f..d0ec7d9f 100644
--- a/shared/nm-utils/nm-test-utils.h
+++ b/shared/nm-utils/nm-test-utils.h
@@ -1144,12 +1144,13 @@ nmtst_uuid_generate (void)
 
 #endif
 
-#define NMTST_SWAP(x,y) \
+#define NMTST_SWAP(x, y) \
 	G_STMT_START { \
-		char __nmtst_swap_temp[sizeof(x) == sizeof(y) ? (signed) sizeof(x) : -1]; \
-		memcpy(__nmtst_swap_temp, &y, sizeof(x)); \
-		memcpy(&y,                &x, sizeof(x)); \
-		memcpy(&x, __nmtst_swap_temp, sizeof(x)); \
+		char __nmtst_swap_temp[sizeof((x)) == sizeof((y)) ? (signed) sizeof((x)) : -1]; \
+		\
+		memcpy(__nmtst_swap_temp, &(y),              sizeof (__nmtst_swap_temp)); \
+		memcpy(&(y),              &(x),              sizeof (__nmtst_swap_temp)); \
+		memcpy(&(x),              __nmtst_swap_temp, sizeof (__nmtst_swap_temp)); \
 	} G_STMT_END
 
 #define nmtst_assert_str_has_substr(str, substr) \
diff --git a/shared/nm-utils/nm-time-utils.c b/shared/nm-utils/nm-time-utils.c
deleted file mode 100644
index ae526c34..00000000
--- a/shared/nm-utils/nm-time-utils.c
+++ /dev/null
@@ -1,273 +0,0 @@
-/* NetworkManager -- Network link manager
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA.
- *
- * (C) Copyright 2018 Red Hat, Inc.
- */
-
-#include "nm-default.h"
-
-#include "nm-time-utils.h"
-
-/*****************************************************************************/
-
-typedef struct {
-	/* the offset to the native clock, in seconds. */
-	gint64 offset_sec;
-	clockid_t clk_id;
-} GlobalState;
-
-static const GlobalState *volatile p_global_state;
-
-static const GlobalState *
-_t_init_global_state (void)
-{
-	static GlobalState global_state = { };
-	static gsize init_once = 0;
-	const GlobalState *p;
-	clockid_t clk_id;
-	struct timespec tp;
-	gint64 offset_sec;
-	int r;
-
-	clk_id = CLOCK_BOOTTIME;
-	r = clock_gettime (clk_id, &tp);
-	if (r == -1 && errno == EINVAL) {
-		clk_id = CLOCK_MONOTONIC;
-		r = clock_gettime (clk_id, &tp);
-	}
-
-	/* The only failure we tolerate is that CLOCK_BOOTTIME is not supported.
-	 * Other than that, we rely on kernel to not fail on this. */
-	g_assert (r == 0);
-	g_assert (tp.tv_nsec >= 0 && tp.tv_nsec < NM_UTILS_NS_PER_SECOND);
-
-	/* Calculate an offset for the time stamp.
-	 *
-	 * We always want positive values, because then we can initialize
-	 * a timestamp with 0 and be sure, that it will be less then any
-	 * value nm_utils_get_monotonic_timestamp_*() might return.
-	 * For this to be true also for nm_utils_get_monotonic_timestamp_s() at
-	 * early boot, we have to shift the timestamp to start counting at
-	 * least from 1 second onward.
-	 *
-	 * Another advantage of shifting is, that this way we make use of the whole 31 bit
-	 * range of signed int, before the time stamp for nm_utils_get_monotonic_timestamp_s()
-	 * wraps (~68 years).
-	 **/
-	offset_sec = (- ((gint64) tp.tv_sec)) + 1;
-
-	if (!g_once_init_enter (&init_once)) {
-		/* there was a race. We expect the pointer to be fully initialized now. */
-		p = g_atomic_pointer_get (&p_global_state);
-		g_assert (p);
-		return p;
-	}
-
-	global_state.offset_sec = offset_sec;
-	global_state.clk_id = clk_id;
-	p = &global_state;
-	g_atomic_pointer_set (&p_global_state, p);
-	g_once_init_leave (&init_once, 1);
-
-	_nm_utils_monotonic_timestamp_initialized (&tp,
-	                                           p->offset_sec,
-	                                           p->clk_id == CLOCK_BOOTTIME);
-
-	return p;
-}
-
-#define _t_get_global_state() \
-	({ \
-		const GlobalState *_p; \
-		\
-		_p = g_atomic_pointer_get (&p_global_state); \
-		(G_LIKELY (_p) ? _p : _t_init_global_state ()); \
-	})
-
-#define _t_clock_gettime_eval(p, tp) \
-	({ \
-		struct timespec *const _tp = (tp); \
-		const GlobalState *const _p2 = (p); \
-		int _r; \
-		\
-		nm_assert (_tp); \
-		\
-		_r = clock_gettime (_p2->clk_id, _tp); \
-		\
-		nm_assert (_r == 0); \
-		nm_assert (_tp->tv_nsec >= 0 && _tp->tv_nsec < NM_UTILS_NS_PER_SECOND); \
-		\
-		_p2; \
-	})
-
-#define _t_clock_gettime(tp) \
-	_t_clock_gettime_eval (_t_get_global_state (), tp);
-
-/*****************************************************************************/
-
-/**
- * nm_utils_get_monotonic_timestamp_ns:
- *
- * Returns: a monotonically increasing time stamp in nanoseconds,
- * starting at an unspecified offset. See clock_gettime(), %CLOCK_BOOTTIME.
- *
- * The returned value will start counting at an undefined point
- * in the past and will always be positive.
- *
- * All the nm_utils_get_monotonic_timestamp_*s functions return the same
- * timestamp but in different scales (nsec, usec, msec, sec).
- **/
-gint64
-nm_utils_get_monotonic_timestamp_ns (void)
-{
-	const GlobalState *p;
-	struct timespec tp;
-
-	p = _t_clock_gettime (&tp);
-
-	/* Although the result will always be positive, we return a signed
-	 * integer, which makes it easier to calculate time differences (when
-	 * you want to subtract signed values).
-	 **/
-	return (((gint64) tp.tv_sec) + p->offset_sec) * NM_UTILS_NS_PER_SECOND +
-	       tp.tv_nsec;
-}
-
-/**
- * nm_utils_get_monotonic_timestamp_us:
- *
- * Returns: a monotonically increasing time stamp in microseconds,
- * starting at an unspecified offset. See clock_gettime(), %CLOCK_BOOTTIME.
- *
- * The returned value will start counting at an undefined point
- * in the past and will always be positive.
- *
- * All the nm_utils_get_monotonic_timestamp_*s functions return the same
- * timestamp but in different scales (nsec, usec, msec, sec).
- **/
-gint64
-nm_utils_get_monotonic_timestamp_us (void)
-{
-	const GlobalState *p;
-	struct timespec tp;
-
-	p = _t_clock_gettime (&tp);
-
-	/* Although the result will always be positive, we return a signed
-	 * integer, which makes it easier to calculate time differences (when
-	 * you want to subtract signed values).
-	 **/
-	return (((gint64) tp.tv_sec) + p->offset_sec) * ((gint64) G_USEC_PER_SEC) +
-	       (tp.tv_nsec / (NM_UTILS_NS_PER_SECOND/G_USEC_PER_SEC));
-}
-
-/**
- * nm_utils_get_monotonic_timestamp_ms:
- *
- * Returns: a monotonically increasing time stamp in milliseconds,
- * starting at an unspecified offset. See clock_gettime(), %CLOCK_BOOTTIME.
- *
- * The returned value will start counting at an undefined point
- * in the past and will always be positive.
- *
- * All the nm_utils_get_monotonic_timestamp_*s functions return the same
- * timestamp but in different scales (nsec, usec, msec, sec).
- **/
-gint64
-nm_utils_get_monotonic_timestamp_ms (void)
-{
-	const GlobalState *p;
-	struct timespec tp;
-
-	p = _t_clock_gettime (&tp);
-
-	/* Although the result will always be positive, we return a signed
-	 * integer, which makes it easier to calculate time differences (when
-	 * you want to subtract signed values).
-	 **/
-	return (((gint64) tp.tv_sec) + p->offset_sec) * ((gint64) 1000) +
-	       (tp.tv_nsec / (NM_UTILS_NS_PER_SECOND/1000));
-}
-
-/**
- * nm_utils_get_monotonic_timestamp_s:
- *
- * Returns: nm_utils_get_monotonic_timestamp_ms() in seconds (throwing
- * away sub second parts). The returned value will always be positive.
- *
- * This value wraps after roughly 68 years which should be fine for any
- * practical purpose.
- *
- * All the nm_utils_get_monotonic_timestamp_*s functions return the same
- * timestamp but in different scales (nsec, usec, msec, sec).
- **/
-gint32
-nm_utils_get_monotonic_timestamp_s (void)
-{
-	const GlobalState *p;
-	struct timespec tp;
-
-	p = _t_clock_gettime (&tp);
-
-	return (((gint64) tp.tv_sec) + p->offset_sec);
-}
-
-/**
- * nm_utils_monotonic_timestamp_as_boottime:
- * @timestamp: the monotonic-timestamp that should be converted into CLOCK_BOOTTIME.
- * @timestamp_ns_per_tick: How many nano seconds make one unit of @timestamp? E.g. if
- * @timestamp is in unit seconds, pass %NM_UTILS_NS_PER_SECOND; @timestamp in nano
- * seconds, pass 1; @timestamp in milli seconds, pass %NM_UTILS_NS_PER_SECOND/1000; etc.
- *
- * Returns: the monotonic-timestamp as CLOCK_BOOTTIME, as returned by clock_gettime().
- * The unit is the same as the passed in @timestamp basd on @timestamp_ns_per_tick.
- * E.g. if you passed @timestamp in as seconds, it will return boottime in seconds.
- * If @timestamp is a non-positive, it returns -1. Note that a (valid) monotonic-timestamp
- * is always positive.
- *
- * On older kernels that don't support CLOCK_BOOTTIME, the returned time is instead CLOCK_MONOTONIC.
- **/
-gint64
-nm_utils_monotonic_timestamp_as_boottime (gint64 timestamp, gint64 timestamp_ns_per_tick)
-{
-	const GlobalState *p;
-	gint64 offset;
-
-	/* only support ns-per-tick being a multiple of 10. */
-	g_return_val_if_fail (timestamp_ns_per_tick == 1
-	                      || (timestamp_ns_per_tick > 0 &&
-	                          timestamp_ns_per_tick <= NM_UTILS_NS_PER_SECOND &&
-	                          timestamp_ns_per_tick % 10 == 0),
-	                      -1);
-
-	/* Check that the timestamp is in a valid range. */
-	g_return_val_if_fail (timestamp >= 0, -1);
-
-	/* if the caller didn't yet ever fetch a monotonic-timestamp, he cannot pass any meaningful
-	 * value (because he has no idea what these timestamps would be). That would be a bug. */
-	nm_assert (g_atomic_pointer_get (&p_global_state));
-
-	p = _t_get_global_state ();
-
-	/* calculate the offset of monotonic-timestamp to boottime. offset_s is <= 1. */
-	offset = p->offset_sec * (NM_UTILS_NS_PER_SECOND / timestamp_ns_per_tick);
-
-	/* check for overflow. */
-	g_return_val_if_fail (offset > 0 || timestamp < G_MAXINT64 + offset, G_MAXINT64);
-
-	return timestamp - offset;
-}
diff --git a/shared/nm-utils/nm-time-utils.h b/shared/nm-utils/nm-time-utils.h
deleted file mode 100644
index 7e4f4f25..00000000
--- a/shared/nm-utils/nm-time-utils.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/* NetworkManager -- Network link manager
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA.
- *
- * (C) Copyright 2018 Red Hat, Inc.
- */
-
-#ifndef __NM_TIME_UTILS_H__
-#define __NM_TIME_UTILS_H__
-
-gint64 nm_utils_get_monotonic_timestamp_ns (void);
-gint64 nm_utils_get_monotonic_timestamp_us (void);
-gint64 nm_utils_get_monotonic_timestamp_ms (void);
-gint32 nm_utils_get_monotonic_timestamp_s (void);
-gint64 nm_utils_monotonic_timestamp_as_boottime (gint64 timestamp, gint64 timestamp_ticks_per_ns);
-
-static inline gint64
-nm_utils_get_monotonic_timestamp_ns_cached (gint64 *cache_now)
-{
-	return    (*cache_now)
-	       ?: (*cache_now = nm_utils_get_monotonic_timestamp_ns ());
-}
-
-struct timespec;
-
-/* this function must be implemented to handle the notification when
- * the first monotonic-timestamp is fetched. */
-extern void _nm_utils_monotonic_timestamp_initialized (const struct timespec *tp,
-                                                       gint64 offset_sec,
-                                                       gboolean is_boottime);
-
-#endif /* __NM_TIME_UTILS_H__ */
diff --git a/shared/nm-utils/nm-udev-utils.c b/shared/nm-utils/nm-udev-utils.c
deleted file mode 100644
index 5d0919b3..00000000
--- a/shared/nm-utils/nm-udev-utils.c
+++ /dev/null
@@ -1,291 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-/* nm-udev-utils.c - udev utils functions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Copyright (C) 2017 Red Hat, Inc.
- */
-
-#include "nm-default.h"
-
-#include "nm-udev-utils.h"
-
-#include <libudev.h>
-
-struct _NMPUdevClient {
-	char **subsystems;
-	GSource *watch_source;
-	struct udev *udev;
-	struct udev_monitor *monitor;
-	NMUdevClientEvent event_handler;
-	gpointer event_user_data;
-};
-
-/*****************************************************************************/
-
-gboolean
-nm_udev_utils_property_as_boolean (const char *uproperty)
-{
-	/* taken from g_udev_device_get_property_as_boolean() */
-
-	if (uproperty) {
-		if (   strcmp (uproperty, "1") == 0
-		    || g_ascii_strcasecmp (uproperty, "true") == 0)
-			return TRUE;
-	}
-	return FALSE;
-}
-
-const char *
-nm_udev_utils_property_decode (const char *uproperty, char **to_free)
-{
-	const char *p;
-	char *unescaped = NULL;
-	char *n = NULL;
-
-	if (!uproperty) {
-		*to_free = NULL;
-		return NULL;
-	}
-
-	p = uproperty;
-	while (*p) {
-		int a, b;
-
-		if (   p[0] == '\\'
-		    && p[1] == 'x'
-		    && (a = g_ascii_xdigit_value (p[2])) >= 0
-		    && (b = g_ascii_xdigit_value (p[3])) >= 0
-		    && (a || b)) {
-			if (!n) {
-				gssize l = p - uproperty;
-
-				unescaped = g_malloc (l + strlen (p) + 1 - 3);
-				memcpy (unescaped, uproperty, l);
-				n = &unescaped[l];
-			}
-			*n++ = (a << 4) | b;
-			p += 4;
-		} else {
-			if (n)
-				*n++ = *p;
-			p++;
-		}
-	}
-
-	if (!n) {
-		*to_free = NULL;
-		return uproperty;
-	}
-
-	*n++ = '\0';
-	return (*to_free = unescaped);
-}
-
-char *
-nm_udev_utils_property_decode_cp (const char *uproperty)
-{
-	char *cpy;
-
-	uproperty = nm_udev_utils_property_decode (uproperty, &cpy);
-	return cpy ?: g_strdup (uproperty);
-}
-
-/*****************************************************************************/
-
-static void
-_subsystem_split (const char *subsystem_full,
-                  const char **out_subsystem,
-                  const char **out_devtype,
-                  char **to_free)
-{
-	char *tmp, *s;
-
-	nm_assert (subsystem_full);
-	nm_assert (out_subsystem);
-	nm_assert (out_devtype);
-	nm_assert (to_free);
-
-	s = strstr (subsystem_full, "/");
-	if (s) {
-		tmp = g_strdup (subsystem_full);
-		s = &tmp[s - subsystem_full];
-		*s = '\0';
-		*out_subsystem = tmp;
-		*out_devtype = &s[1];
-		*to_free = tmp;
-	} else {
-		*out_subsystem = subsystem_full;
-		*out_devtype = NULL;
-		*to_free = NULL;
-	}
-}
-
-static struct udev_enumerate *
-nm_udev_utils_enumerate (struct udev *uclient,
-                         const char *const*subsystems)
-{
-	struct udev_enumerate *enumerate;
-	guint n;
-
-	enumerate = udev_enumerate_new (uclient);
-
-	if (subsystems) {
-		for (n = 0; subsystems[n]; n++) {
-			const char *subsystem;
-			const char *devtype;
-			gs_free char *to_free = NULL;
-
-			_subsystem_split (subsystems[n], &subsystem, &devtype, &to_free);
-
-			udev_enumerate_add_match_subsystem (enumerate, subsystem);
-
-			if (devtype != NULL)
-				udev_enumerate_add_match_property (enumerate, "DEVTYPE", devtype);
-		}
-	}
-
-	return enumerate;
-}
-
-struct udev *
-nm_udev_client_get_udev (NMUdevClient *self)
-{
-	g_return_val_if_fail (self, NULL);
-
-	return self->udev;
-}
-
-struct udev_enumerate *
-nm_udev_client_enumerate_new (NMUdevClient *self)
-{
-	g_return_val_if_fail (self, NULL);
-
-	return nm_udev_utils_enumerate (self->udev, (const char *const*) self->subsystems);
-}
-
-/*****************************************************************************/
-
-static gboolean
-monitor_event (GIOChannel *source,
-               GIOCondition condition,
-               gpointer user_data)
-{
-	NMUdevClient *self = user_data;
-	struct udev_device *udevice;
-
-	if (!self->monitor)
-		goto out;
-
-	udevice = udev_monitor_receive_device (self->monitor);
-	if (udevice == NULL)
-		goto out;
-
-	self->event_handler (self,
-	                     udevice,
-	                     self->event_user_data);
-	udev_device_unref (udevice);
-
-out:
-	return TRUE;
-}
-
-/**
- * nm_udev_client_new:
- * @subsystems: the subsystems
- * @event_handler: callback for events
- * @event_user_data: user-data for @event_handler
- *
- * Basically, it is g_udev_client_new(), and most notably
- * g_udev_client_constructed().
- *
- * Returns: a new NMUdevClient instance.
- */
-NMUdevClient *
-nm_udev_client_new (const char *const*subsystems,
-                    NMUdevClientEvent event_handler,
-                    gpointer event_user_data)
-{
-	NMUdevClient *self;
-	GIOChannel *channel;
-	guint n;
-
-	self = g_slice_new0 (NMUdevClient);
-
-	self->event_handler = event_handler;
-	self->event_user_data = event_user_data;
-	self->subsystems = subsystems && subsystems[0] ? g_strdupv ((char **) subsystems) : NULL;
-
-	self->udev = udev_new ();
-	if (!self->udev)
-		goto fail;
-
-	/* connect to event source */
-	if (self->event_handler) {
-		self->monitor = udev_monitor_new_from_netlink (self->udev, "udev");
-		if (!self->monitor)
-			goto fail;
-
-		if (self->subsystems) {
-			/* install subsystem filters to only wake up for certain events */
-			for (n = 0; self->subsystems[n]; n++) {
-				gs_free char *to_free = NULL;
-				const char *subsystem;
-				const char *devtype;
-
-				_subsystem_split (self->subsystems[n], &subsystem, &devtype, &to_free);
-				udev_monitor_filter_add_match_subsystem_devtype (self->monitor, subsystem, devtype);
-			}
-
-			/* listen to events, and buffer them */
-			udev_monitor_set_receive_buffer_size (self->monitor, 4*1024*1024);
-			udev_monitor_enable_receiving (self->monitor);
-			channel = g_io_channel_unix_new (udev_monitor_get_fd (self->monitor));
-			self->watch_source = g_io_create_watch (channel, G_IO_IN);
-			g_io_channel_unref (channel);
-			g_source_set_callback (self->watch_source, (GSourceFunc)(void (*) (void)) monitor_event, self, NULL);
-			g_source_attach (self->watch_source, g_main_context_get_thread_default ());
-			g_source_unref (self->watch_source);
-		}
-	}
-
-	return self;
-
-fail:
-	return nm_udev_client_unref (self);
-}
-
-NMUdevClient *
-nm_udev_client_unref (NMUdevClient *self)
-{
-	if (!self)
-		return NULL;
-
-	if (self->watch_source) {
-		g_source_destroy (self->watch_source);
-		self->watch_source = NULL;
-	}
-
-	udev_monitor_unref (self->monitor);
-	self->monitor = NULL;
-	udev_unref (self->udev);
-	self->udev = NULL;
-
-	g_strfreev (self->subsystems);
-
-	g_slice_free (NMUdevClient, self);
-
-	return NULL;
-}
diff --git a/shared/nm-utils/nm-udev-utils.h b/shared/nm-utils/nm-udev-utils.h
deleted file mode 100644
index 911e8a27..00000000
--- a/shared/nm-utils/nm-udev-utils.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-/* nm-udev-utils.h - udev utils functions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Copyright (C) 2017 Red Hat, Inc.
- */
-
-#ifndef __NM_UDEV_UTILS_H__
-#define __NM_UDEV_UTILS_H__
-
-struct udev;
-struct udev_device;
-struct udev_enumerate;
-
-gboolean nm_udev_utils_property_as_boolean (const char *uproperty);
-const char *nm_udev_utils_property_decode    (const char *uproperty, char **to_free);
-char       *nm_udev_utils_property_decode_cp (const char *uproperty);
-
-typedef struct _NMPUdevClient NMUdevClient;
-
-typedef void (*NMUdevClientEvent) (NMUdevClient *udev_client,
-                                   struct udev_device *udevice,
-                                   gpointer event_user_data);
-
-NMUdevClient *nm_udev_client_new (const char *const*subsystems,
-                                  NMUdevClientEvent event_handler,
-                                  gpointer event_user_data);
-
-NMUdevClient *nm_udev_client_unref (NMUdevClient *self);
-
-struct udev *nm_udev_client_get_udev (NMUdevClient *self);
-
-struct udev_enumerate *nm_udev_client_enumerate_new (NMUdevClient *self);
-
-#endif /* __NM_UDEV_UTILS_H__ */
diff --git a/shared/nm-utils/nm-vpn-editor-plugin-call.h b/shared/nm-utils/nm-vpn-editor-plugin-call.h
index 78d041df..fd982acf 100644
--- a/shared/nm-utils/nm-vpn-editor-plugin-call.h
+++ b/shared/nm-utils/nm-vpn-editor-plugin-call.h
@@ -32,7 +32,7 @@
 #include <NetworkManager.h>
 
 /* we make use of other internal header files, you need those too. */
-#include "nm-macros-internal.h"
+#include "nm-glib-aux/nm-macros-internal.h"
 
 /*****************************************************************************/
 
diff --git a/shared/nm-utils/tests/test-shared-general.c b/shared/nm-utils/tests/test-shared-general.c
index d53b21d9..83cffd7f 100644
--- a/shared/nm-utils/tests/test-shared-general.c
+++ b/shared/nm-utils/tests/test-shared-general.c
@@ -21,9 +21,9 @@
 
 #include "nm-default.h"
 
-#include "nm-utils/nm-time-utils.h"
-#include "nm-utils/nm-random-utils.h"
-#include "nm-utils/unaligned.h"
+#include "nm-std-aux/unaligned.h"
+#include "nm-glib-aux/nm-random-utils.h"
+#include "nm-glib-aux/nm-time-utils.h"
 
 #include "nm-utils/nm-test-utils.h"
 
@@ -248,6 +248,201 @@ test_unaligned (void)
 
 /*****************************************************************************/
 
+static void
+_strv_cmp_fuzz_input (const char *const*in,
+                      gssize l,
+                      const char ***out_strv_free_shallow,
+                      char ***out_strv_free_deep,
+                      const char *const* *out_s1,
+                      const char *const* *out_s2)
+{
+	const char **strv;
+	gsize i;
+
+	/* Fuzz the input argument. It will return two output arrays that are semantically
+	 * equal the input. */
+
+	if (nmtst_get_rand_bool ()) {
+		char **ss;
+
+		if (l < 0)
+			ss = g_strdupv ((char **) in);
+		else if (l == 0) {
+			ss =   nmtst_get_rand_bool ()
+			     ? NULL
+			     : g_new0 (char *, 1);
+		} else {
+			ss = nm_memdup (in, sizeof (const char *) * l);
+			for (i = 0; i < (gsize) l; i++)
+				ss[i] = g_strdup (ss[i]);
+		}
+		strv = (const char **) ss;
+		*out_strv_free_deep = ss;
+	} else {
+		if (l < 0) {
+			strv =   in
+			       ? nm_memdup (in, sizeof (const char *) * (NM_PTRARRAY_LEN (in) + 1))
+			       : NULL;
+		} else if (l == 0) {
+			strv =   nmtst_get_rand_bool ()
+			       ? NULL
+			       : g_new0 (const char *, 1);
+		} else
+			strv = nm_memdup (in, sizeof (const char *) * l);
+		*out_strv_free_shallow = strv;
+	}
+
+	*out_s1 = in;
+	*out_s2 = strv;
+
+	if (nmtst_get_rand_bool ()) {
+		/* randomly swap the original and the clone. That means, out_s1 is either
+		 * the input argument (as-is) or the sementically equal clone. */
+		NMTST_SWAP (*out_s1, *out_s2);
+	}
+	if (nmtst_get_rand_bool ()) {
+		/* randomly make s1 and s2 the same. This is for testing that
+		 * comparing two identical pointers yields the same result. */
+		*out_s2 = *out_s1;
+	}
+}
+
+static void
+_strv_cmp_free_deep (char **strv,
+                     gssize len)
+{
+	gssize i;
+
+	if (strv) {
+		if (len < 0)
+			g_strfreev (strv);
+		else {
+			for (i = 0; i < len; i++)
+				g_free (strv[i]);
+			g_free (strv);
+		}
+	}
+}
+
+static void
+test_strv_cmp (void)
+{
+	const char *const strv0[1] = { };
+	const char *const strv1[2] = { "", };
+
+#define _STRV_CMP(a1, l1, a2, l2, equal) \
+	G_STMT_START { \
+		gssize _l1 = (l1); \
+		gssize _l2 = (l2); \
+		const char *const*_a1; \
+		const char *const*_a2; \
+		const char *const*_a1x; \
+		const char *const*_a2x; \
+		char **_a1_free_deep = NULL; \
+		char **_a2_free_deep = NULL; \
+		gs_free const char **_a1_free_shallow = NULL; \
+		gs_free const char **_a2_free_shallow = NULL; \
+		int _c1, _c2; \
+		\
+		_strv_cmp_fuzz_input ((a1), _l1, &_a1_free_shallow, &_a1_free_deep, &_a1, &_a1x); \
+		_strv_cmp_fuzz_input ((a2), _l2, &_a2_free_shallow, &_a2_free_deep, &_a2, &_a2x); \
+		\
+		_c1 = _nm_utils_strv_cmp_n (_a1, _l1, _a2, _l2); \
+		_c2 = _nm_utils_strv_cmp_n (_a2, _l2, _a1, _l1); \
+		if (equal) { \
+			g_assert_cmpint (_c1, ==, 0); \
+			g_assert_cmpint (_c2, ==, 0); \
+		} else { \
+			g_assert_cmpint (_c1, ==, -1); \
+			g_assert_cmpint (_c2, ==, 1); \
+		} \
+		\
+		/* Compare with self. _strv_cmp_fuzz_input() randomly swapped the arguments (_a1 and _a1x).
+		 * Either way, the arrays must compare equal to their semantically equal alternative. */ \
+		g_assert_cmpint (_nm_utils_strv_cmp_n (_a1, _l1, _a1x, _l1), ==, 0); \
+		g_assert_cmpint (_nm_utils_strv_cmp_n (_a2, _l2, _a2x, _l2), ==, 0); \
+		\
+		_strv_cmp_free_deep (_a1_free_deep, _l1); \
+		_strv_cmp_free_deep (_a2_free_deep, _l2); \
+	} G_STMT_END
+
+	_STRV_CMP (NULL,  -1, NULL,  -1, TRUE);
+
+	_STRV_CMP (NULL,  -1, NULL,   0, FALSE);
+	_STRV_CMP (NULL,  -1, strv0,  0, FALSE);
+	_STRV_CMP (NULL,  -1, strv0, -1, FALSE);
+
+	_STRV_CMP (NULL,   0, NULL,   0, TRUE);
+	_STRV_CMP (NULL,   0, strv0,  0, TRUE);
+	_STRV_CMP (NULL,   0, strv0, -1, TRUE);
+	_STRV_CMP (strv0,  0, strv0,  0, TRUE);
+	_STRV_CMP (strv0,  0, strv0, -1, TRUE);
+	_STRV_CMP (strv0, -1, strv0, -1, TRUE);
+
+	_STRV_CMP (NULL,   0, strv1, -1, FALSE);
+	_STRV_CMP (NULL,   0, strv1,  1, FALSE);
+	_STRV_CMP (strv0,  0, strv1, -1, FALSE);
+	_STRV_CMP (strv0,  0, strv1,  1, FALSE);
+	_STRV_CMP (strv0, -1, strv1, -1, FALSE);
+	_STRV_CMP (strv0, -1, strv1,  1, FALSE);
+
+	_STRV_CMP (strv1, -1, strv1,  1, TRUE);
+	_STRV_CMP (strv1,  1, strv1,  1, TRUE);
+}
+
+/*****************************************************************************/
+
+static void
+_do_strstrip_avoid_copy (const char *str)
+{
+	gs_free char *str1 = g_strdup (str);
+	gs_free char *str2 = g_strdup (str);
+	gs_free char *str3 = NULL;
+	gs_free char *str4 = NULL;
+	const char *s3;
+	const char *s4;
+
+	if (str1)
+		g_strstrip (str1);
+
+	nm_strstrip (str2);
+
+	g_assert_cmpstr (str1, ==, str2);
+
+	s3 = nm_strstrip_avoid_copy (str, &str3);
+	g_assert_cmpstr (str1, ==, s3);
+
+	s4 = nm_strstrip_avoid_copy_a (10, str, &str4);
+	g_assert_cmpstr (str1, ==, s4);
+	g_assert (!str == !s4);
+	g_assert (!s4 || strlen (s4) <= strlen (str));
+	if (s4 && s4 == &str[strlen (str) - strlen (s4)]) {
+		g_assert (!str4);
+		g_assert (s3 == s4);
+	} else if (s4 && strlen (s4) >= 10) {
+		g_assert (str4);
+		g_assert (s4 == str4);
+	} else
+		g_assert (!str4);
+
+	if (!nm_streq0 (str1, str))
+		_do_strstrip_avoid_copy (str1);
+}
+
+static void
+test_strstrip_avoid_copy (void)
+{
+	_do_strstrip_avoid_copy (NULL);
+	_do_strstrip_avoid_copy ("");
+	_do_strstrip_avoid_copy (" ");
+	_do_strstrip_avoid_copy (" a ");
+	_do_strstrip_avoid_copy (" 012345678 ");
+	_do_strstrip_avoid_copy (" 0123456789 ");
+	_do_strstrip_avoid_copy (" 01234567890 ");
+	_do_strstrip_avoid_copy (" 012345678901 ");
+}
+/*****************************************************************************/
+
 NMTST_DEFINE ();
 
 int main (int argc, char **argv)
@@ -261,6 +456,8 @@ int main (int argc, char **argv)
 	g_test_add_func ("/general/test_nm_strndup_a", test_nm_strndup_a);
 	g_test_add_func ("/general/test_nm_ip4_addr_is_localhost", test_nm_ip4_addr_is_localhost);
 	g_test_add_func ("/general/test_unaligned", test_unaligned);
+	g_test_add_func ("/general/test_strv_cmp", test_strv_cmp);
+	g_test_add_func ("/general/test_strstrip_avoid_copy", test_strstrip_avoid_copy);
 
 	return g_test_run ();
 }
diff --git a/shared/nm-utils/unaligned.h b/shared/nm-utils/unaligned.h
deleted file mode 100644
index 00c17f87..00000000
--- a/shared/nm-utils/unaligned.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1+ */
-#pragma once
-
-#include <endian.h>
-#include <stdint.h>
-
-/* BE */
-
-static inline uint16_t unaligned_read_be16(const void *_u) {
-        const struct __attribute__((__packed__, __may_alias__)) { uint16_t x; } *u = _u;
-
-        return be16toh(u->x);
-}
-
-static inline uint32_t unaligned_read_be32(const void *_u) {
-        const struct __attribute__((__packed__, __may_alias__)) { uint32_t x; } *u = _u;
-
-        return be32toh(u->x);
-}
-
-static inline uint64_t unaligned_read_be64(const void *_u) {
-        const struct __attribute__((__packed__, __may_alias__)) { uint64_t x; } *u = _u;
-
-        return be64toh(u->x);
-}
-
-static inline void unaligned_write_be16(void *_u, uint16_t a) {
-        struct __attribute__((__packed__, __may_alias__)) { uint16_t x; } *u = _u;
-
-        u->x = be16toh(a);
-}
-
-static inline void unaligned_write_be32(void *_u, uint32_t a) {
-        struct __attribute__((__packed__, __may_alias__)) { uint32_t x; } *u = _u;
-
-        u->x = be32toh(a);
-}
-
-static inline void unaligned_write_be64(void *_u, uint64_t a) {
-        struct __attribute__((__packed__, __may_alias__)) { uint64_t x; } *u = _u;
-
-        u->x = be64toh(a);
-}
-
-/* LE */
-
-static inline uint16_t unaligned_read_le16(const void *_u) {
-        const struct __attribute__((__packed__, __may_alias__)) { uint16_t x; } *u = _u;
-
-        return le16toh(u->x);
-}
-
-static inline uint32_t unaligned_read_le32(const void *_u) {
-        const struct __attribute__((__packed__, __may_alias__)) { uint32_t x; } *u = _u;
-
-        return le32toh(u->x);
-}
-
-static inline uint64_t unaligned_read_le64(const void *_u) {
-        const struct __attribute__((__packed__, __may_alias__)) { uint64_t x; } *u = _u;
-
-        return le64toh(u->x);
-}
-
-static inline void unaligned_write_le16(void *_u, uint16_t a) {
-        struct __attribute__((__packed__, __may_alias__)) { uint16_t x; } *u = _u;
-
-        u->x = le16toh(a);
-}
-
-static inline void unaligned_write_le32(void *_u, uint32_t a) {
-        struct __attribute__((__packed__, __may_alias__)) { uint32_t x; } *u = _u;
-
-        u->x = le32toh(a);
-}
-
-static inline void unaligned_write_le64(void *_u, uint64_t a) {
-        struct __attribute__((__packed__, __may_alias__)) { uint64_t x; } *u = _u;
-
-        u->x = le64toh(a);
-}
-
-#if __BYTE_ORDER == __BIG_ENDIAN
-#define unaligned_read_ne16 unaligned_read_be16
-#define unaligned_read_ne32 unaligned_read_be32
-#define unaligned_read_ne64 unaligned_read_be64
-
-#define unaligned_write_ne16 unaligned_write_be16
-#define unaligned_write_ne32 unaligned_write_be32
-#define unaligned_write_ne64 unaligned_write_be64
-#else
-#define unaligned_read_ne16 unaligned_read_le16
-#define unaligned_read_ne32 unaligned_read_le32
-#define unaligned_read_ne64 unaligned_read_le64
-
-#define unaligned_write_ne16 unaligned_write_le16
-#define unaligned_write_ne32 unaligned_write_le32
-#define unaligned_write_ne64 unaligned_write_le64
-#endif