about summary refs log tree commit diff
path: root/src/libnm-core-aux-intern
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2021-10-01 23:05:04 +0200
committerMichael Biebl <biebl@debian.org>2021-10-01 23:05:04 +0200
commite74c568b07b50b97873fb4ee1d776dedefbd54d6 (patch)
tree3469f17ea9af91f7ff169b890633bda68b0cf76e /src/libnm-core-aux-intern
parentbfe522304da217296e2a61040f58e35ec5d6f3f2 (diff)
New upstream version 1.32.12 upstream/1.32.12
Diffstat (limited to 'src/libnm-core-aux-intern')
-rw-r--r--src/libnm-core-aux-intern/README.md28
-rw-r--r--src/libnm-core-aux-intern/meson.build13
-rw-r--r--src/libnm-core-aux-intern/nm-auth-subject.c468
-rw-r--r--src/libnm-core-aux-intern/nm-auth-subject.h59
-rw-r--r--src/libnm-core-aux-intern/nm-common-macros.h65
-rw-r--r--src/libnm-core-aux-intern/nm-libnm-core-utils.c360
-rw-r--r--src/libnm-core-aux-intern/nm-libnm-core-utils.h169
7 files changed, 1162 insertions, 0 deletions
diff --git a/src/libnm-core-aux-intern/README.md b/src/libnm-core-aux-intern/README.md
new file mode 100644
index 00000000..37e238f1
--- /dev/null
+++ b/src/libnm-core-aux-intern/README.md
@@ -0,0 +1,28 @@
+libnm-core-aux-intern
+=====================
+
+`libnm-core-aux-intern` is a static library that:
+
+ - uses parts of [`libnm-core-impl`](../libnm-core-impl), that are public API
+   of [`libnm`](../../libnm) (i.e. [`libnm-core-public`](../libnm-core-public)).
+ - that is statically linked into [`libnm-core-impl`](../libnm-core-impl) (and thus
+   [`libnm`](../libnm) and NetworkManager core.
+ - that can also be statically linked into other users of [`libnm`](../libnm).
+
+Basically, it is a static library with utility functions that extends
+[`libnm-core-impl`](../libnm-core-impl) (the part that is public API of libnm),
+but it is also used by [`libnm-core-impl`](../libnm-core-impl) itself.
+
+That means:
+
+  - you can use it everywhere where you either statically link
+    with [`libnm-core-impl`](../libnm-core-impl), or dynamically link with
+    [`libnm`](../../libnm).
+  - you can even use it inside of [`libnm-core-impl`](../libnm-core-impl) itself.
+    This is the difference between `libnm-core-aux-intern` and
+    [`libnm-core-aux-extern`](..libnm-core-aux-extern).
+
+Note that `libnm-core-aux-intern` only uses public API of `libnm`.
+
+This directory should not be added to the include search path. Instead,
+users should fully qualify the include like `#include "libnm-core-aux-intern/nm-auth-subject.h"`.
diff --git a/src/libnm-core-aux-intern/meson.build b/src/libnm-core-aux-intern/meson.build
new file mode 100644
index 00000000..a58921e3
--- /dev/null
+++ b/src/libnm-core-aux-intern/meson.build
@@ -0,0 +1,13 @@
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
+libnm_core_aux_intern = static_library(
+  'nm-core-aux-intern',
+  sources: files(
+    'nm-auth-subject.c',
+    'nm-libnm-core-utils.c',
+  ),
+  dependencies: [
+    libnm_core_public_dep,
+    glib_dep,
+  ],
+)
diff --git a/src/libnm-core-aux-intern/nm-auth-subject.c b/src/libnm-core-aux-intern/nm-auth-subject.c
new file mode 100644
index 00000000..536b4e47
--- /dev/null
+++ b/src/libnm-core-aux-intern/nm-auth-subject.c
@@ -0,0 +1,468 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2013 - 2014 Red Hat, Inc.
+ */
+
+/**
+ * SECTION:nm-auth-subject
+ * @short_description: Encapsulates authentication information about a requestor
+ *
+ * #NMAuthSubject encpasulates identifying information about an entity that
+ * makes requests, like process identifier and user UID.
+ */
+
+#include "libnm-glib-aux/nm-default-glib-i18n-lib.h"
+
+#include "nm-auth-subject.h"
+
+#include <stdlib.h>
+
+enum {
+    PROP_0,
+    PROP_SUBJECT_TYPE,
+    PROP_UNIX_PROCESS_DBUS_SENDER,
+    PROP_UNIX_PROCESS_PID,
+    PROP_UNIX_PROCESS_UID,
+    PROP_UNIX_SESSION_ID,
+
+    PROP_LAST,
+};
+
+typedef struct {
+    NMAuthSubjectType subject_type;
+    struct {
+        gulong  pid;
+        gulong  uid;
+        guint64 start_time;
+        char *  dbus_sender;
+    } unix_process;
+
+    struct {
+        char *id;
+    } unix_session;
+} NMAuthSubjectPrivate;
+
+struct _NMAuthSubject {
+    GObject              parent;
+    NMAuthSubjectPrivate _priv;
+};
+
+struct _NMAuthSubjectClass {
+    GObjectClass parent;
+};
+
+G_DEFINE_TYPE(NMAuthSubject, nm_auth_subject, G_TYPE_OBJECT)
+
+#define NM_AUTH_SUBJECT_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMAuthSubject, NM_IS_AUTH_SUBJECT)
+
+/*****************************************************************************/
+
+#define CHECK_SUBJECT(self, error_value)                         \
+    NMAuthSubjectPrivate *priv;                                  \
+    g_return_val_if_fail(NM_IS_AUTH_SUBJECT(self), error_value); \
+    priv = NM_AUTH_SUBJECT_GET_PRIVATE(self);
+
+#define CHECK_SUBJECT_TYPED(self, expected_subject_type, error_value) \
+    CHECK_SUBJECT(self, error_value);                                 \
+    g_return_val_if_fail(priv->subject_type == (expected_subject_type), error_value);
+
+const char *
+nm_auth_subject_to_string(NMAuthSubject *self, char *buf, gsize buf_len)
+{
+    CHECK_SUBJECT(self, NULL);
+
+    switch (priv->subject_type) {
+    case NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS:
+        g_snprintf(buf,
+                   buf_len,
+                   "unix-process[pid=%lu, uid=%lu, start=%llu]",
+                   (unsigned long) priv->unix_process.pid,
+                   (unsigned long) priv->unix_process.uid,
+                   (unsigned long long) priv->unix_process.start_time);
+        break;
+    case NM_AUTH_SUBJECT_TYPE_INTERNAL:
+        g_strlcpy(buf, "internal", buf_len);
+        break;
+    case NM_AUTH_SUBJECT_TYPE_UNIX_SESSION:
+        g_snprintf(buf, buf_len, "unix-session[id=%s]", priv->unix_session.id);
+        break;
+    default:
+        g_strlcpy(buf, "invalid", buf_len);
+        break;
+    }
+    return buf;
+}
+
+/* returns a floating variant */
+GVariant *
+nm_auth_subject_unix_to_polkit_gvariant(NMAuthSubject *self)
+{
+    GVariantBuilder builder;
+    CHECK_SUBJECT(self, NULL);
+
+    switch (priv->subject_type) {
+    case NM_AUTH_SUBJECT_TYPE_UNIX_SESSION:
+        g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}"));
+        g_variant_builder_add(&builder,
+                              "{sv}",
+                              "session-id",
+                              g_variant_new_string(priv->unix_session.id));
+        return g_variant_new("(sa{sv})", "unix-session", &builder);
+
+    case NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS:
+        g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}"));
+        g_variant_builder_add(&builder,
+                              "{sv}",
+                              "pid",
+                              g_variant_new_uint32(priv->unix_process.pid));
+        g_variant_builder_add(&builder,
+                              "{sv}",
+                              "start-time",
+                              g_variant_new_uint64(priv->unix_process.start_time));
+        g_variant_builder_add(&builder, "{sv}", "uid", g_variant_new_int32(priv->unix_process.uid));
+        return g_variant_new("(sa{sv})", "unix-process", &builder);
+
+    default:
+        g_return_val_if_reached(NULL);
+    }
+}
+
+NMAuthSubjectType
+nm_auth_subject_get_subject_type(NMAuthSubject *subject)
+{
+    CHECK_SUBJECT(subject, NM_AUTH_SUBJECT_TYPE_INVALID);
+
+    return priv->subject_type;
+}
+
+gulong
+nm_auth_subject_get_unix_process_pid(NMAuthSubject *subject)
+{
+    CHECK_SUBJECT_TYPED(subject, NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS, G_MAXULONG);
+
+    return priv->unix_process.pid;
+}
+
+gulong
+nm_auth_subject_get_unix_process_uid(NMAuthSubject *subject)
+{
+    CHECK_SUBJECT_TYPED(subject, NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS, G_MAXULONG);
+
+    return priv->unix_process.uid;
+}
+
+const char *
+nm_auth_subject_get_unix_process_dbus_sender(NMAuthSubject *subject)
+{
+    CHECK_SUBJECT_TYPED(subject, NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS, NULL);
+
+    return priv->unix_process.dbus_sender;
+}
+
+const char *
+nm_auth_subject_get_unix_session_id(NMAuthSubject *subject)
+{
+    CHECK_SUBJECT_TYPED(subject, NM_AUTH_SUBJECT_TYPE_UNIX_SESSION, NULL);
+
+    return priv->unix_session.id;
+}
+
+/*****************************************************************************/
+
+/**
+ * nm_auth_subject_new_internal():
+ *
+ * Creates a new auth subject representing the NetworkManager process itself.
+ *
+ * Returns: the new #NMAuthSubject
+ */
+NMAuthSubject *
+nm_auth_subject_new_internal(void)
+{
+    return g_object_new(NM_TYPE_AUTH_SUBJECT,
+                        NM_AUTH_SUBJECT_SUBJECT_TYPE,
+                        (int) NM_AUTH_SUBJECT_TYPE_INTERNAL,
+                        NULL);
+}
+
+/**
+ * nm_auth_subject_new_unix_session():
+ *
+ * Creates a new auth subject representing a given unix session.
+ *
+ * Returns: the new #NMAuthSubject
+ */
+NMAuthSubject *
+nm_auth_subject_new_unix_session(const char *session_id)
+{
+    return g_object_new(NM_TYPE_AUTH_SUBJECT,
+                        NM_AUTH_SUBJECT_SUBJECT_TYPE,
+                        (int) NM_AUTH_SUBJECT_TYPE_UNIX_SESSION,
+                        NM_AUTH_SUBJECT_UNIX_SESSION_ID,
+                        session_id,
+                        NULL);
+}
+
+/**
+ * nm_auth_subject_new_unix_process():
+ *
+ * Creates a new auth subject representing a given unix process.
+ *
+ * Returns: the new #NMAuthSubject
+ */
+NMAuthSubject *
+nm_auth_subject_new_unix_process(const char *dbus_sender, gulong pid, gulong uid)
+{
+    return g_object_new(NM_TYPE_AUTH_SUBJECT,
+                        NM_AUTH_SUBJECT_SUBJECT_TYPE,
+                        (int) NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS,
+                        NM_AUTH_SUBJECT_UNIX_PROCESS_DBUS_SENDER,
+                        dbus_sender,
+                        NM_AUTH_SUBJECT_UNIX_PROCESS_PID,
+                        pid,
+                        NM_AUTH_SUBJECT_UNIX_PROCESS_UID,
+                        uid,
+                        NULL);
+}
+
+/**
+ * nm_auth_subject_new_unix_process_self():
+ *
+ * Creates a new auth subject representing the current executing process.
+ *
+ * Returns: the new #NMAuthSubject
+ */
+NMAuthSubject *
+nm_auth_subject_new_unix_process_self(void)
+{
+    return nm_auth_subject_new_unix_process(NULL, getpid(), getuid());
+}
+
+/*****************************************************************************/
+
+static void
+get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+    NMAuthSubjectPrivate *priv = NM_AUTH_SUBJECT_GET_PRIVATE(object);
+
+    switch (prop_id) {
+    case PROP_SUBJECT_TYPE:
+        g_value_set_int(value, priv->subject_type);
+        break;
+    case PROP_UNIX_PROCESS_DBUS_SENDER:
+        g_value_set_string(value, priv->unix_process.dbus_sender);
+        break;
+    case PROP_UNIX_PROCESS_PID:
+        g_value_set_ulong(value, priv->unix_process.pid);
+        break;
+    case PROP_UNIX_PROCESS_UID:
+        g_value_set_ulong(value, priv->unix_process.uid);
+        break;
+    case PROP_UNIX_SESSION_ID:
+        g_value_set_string(value, priv->unix_session.id);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+    NMAuthSubjectPrivate *priv = NM_AUTH_SUBJECT_GET_PRIVATE(object);
+    NMAuthSubjectType     subject_type;
+    int                   i;
+    const char *          str;
+    gulong                id;
+
+    switch (prop_id) {
+    case PROP_SUBJECT_TYPE:
+        /* construct-only */
+        i = g_value_get_int(value);
+        g_return_if_fail(NM_IN_SET(i,
+                                   (int) NM_AUTH_SUBJECT_TYPE_INTERNAL,
+                                   (int) NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS,
+                                   (int) NM_AUTH_SUBJECT_TYPE_UNIX_SESSION));
+        subject_type = i;
+        priv->subject_type |= subject_type;
+        g_return_if_fail(priv->subject_type == subject_type);
+        break;
+    case PROP_UNIX_PROCESS_DBUS_SENDER:
+        /* construct-only */
+        if ((str = g_value_get_string(value))) {
+            priv->subject_type |= NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS;
+            g_return_if_fail(priv->subject_type == NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS);
+            priv->unix_process.dbus_sender = g_strdup(str);
+        }
+        break;
+    case PROP_UNIX_PROCESS_PID:
+        /* construct-only */
+        if ((id = g_value_get_ulong(value)) != G_MAXULONG) {
+            priv->subject_type |= NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS;
+            g_return_if_fail(priv->subject_type == NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS);
+            priv->unix_process.pid = id;
+        }
+        break;
+    case PROP_UNIX_PROCESS_UID:
+        /* construct-only */
+        if ((id = g_value_get_ulong(value)) != G_MAXULONG) {
+            priv->subject_type |= NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS;
+            g_return_if_fail(priv->subject_type == NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS);
+            priv->unix_process.uid = id;
+        }
+        break;
+    case PROP_UNIX_SESSION_ID:
+        /* construct-only */
+        if ((str = g_value_get_string(value))) {
+            priv->subject_type |= NM_AUTH_SUBJECT_TYPE_UNIX_SESSION;
+            g_return_if_fail(priv->subject_type == NM_AUTH_SUBJECT_TYPE_UNIX_SESSION);
+            priv->unix_session.id = g_strdup(str);
+        }
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+_clear_private(NMAuthSubject *self)
+{
+    NMAuthSubjectPrivate *priv = NM_AUTH_SUBJECT_GET_PRIVATE(self);
+
+    priv->subject_type     = NM_AUTH_SUBJECT_TYPE_INVALID;
+    priv->unix_process.pid = G_MAXULONG;
+    priv->unix_process.uid = G_MAXULONG;
+    nm_clear_g_free(&priv->unix_process.dbus_sender);
+
+    nm_clear_g_free(&priv->unix_session.id);
+}
+
+static void
+nm_auth_subject_init(NMAuthSubject *self)
+{
+    _clear_private(self);
+}
+
+static void
+constructed(GObject *object)
+{
+    NMAuthSubject *       self = NM_AUTH_SUBJECT(object);
+    NMAuthSubjectPrivate *priv = NM_AUTH_SUBJECT_GET_PRIVATE(self);
+
+    /* validate that the created instance. */
+
+    switch (priv->subject_type) {
+    case NM_AUTH_SUBJECT_TYPE_INTERNAL:
+        priv->unix_process.pid = G_MAXULONG;
+        priv->unix_process.uid = 0; /* internal uses 'root' user */
+        return;
+    case NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS:
+        /* Ensure pid and uid to be representable as int32.
+         * DBUS treats them as uint32, polkit library as int. */
+        if (priv->unix_process.pid > MIN(G_MAXINT, G_MAXINT32))
+            break;
+        if (priv->unix_process.uid > MIN(G_MAXINT, G_MAXINT32)) {
+            /* for uid==-1, libpolkit-gobject-1 detects the user based on the process id.
+             * Don't bother and require the user id as parameter. */
+            break;
+        }
+
+        priv->unix_process.start_time =
+            nm_utils_get_start_time_for_pid(priv->unix_process.pid, NULL, NULL);
+
+        if (!priv->unix_process.start_time) {
+            /* Is the process already gone? Then fail creation of the auth subject
+             * by clearing the type. */
+            if (kill(priv->unix_process.pid, 0) != 0)
+                _clear_private(self);
+
+            /* Otherwise, although we didn't detect a start_time, the process is still around.
+             * That could be due to procfs mounted with hidepid. So just accept the request.
+             *
+             * Polkit on the other side, will accept 0 and try to lookup /proc/$PID/stat
+             * itself (and if it fails to do so, assume a start-time of 0 and proceed).
+             * The only combination that would fail here, is when NM is able to read the
+             * start-time, but polkit is not. */
+        }
+        return;
+    case NM_AUTH_SUBJECT_TYPE_UNIX_SESSION:
+        return;
+    default:
+        break;
+    }
+
+    _clear_private(self);
+    g_return_if_reached();
+}
+
+static void
+finalize(GObject *object)
+{
+    _clear_private((NMAuthSubject *) object);
+
+    G_OBJECT_CLASS(nm_auth_subject_parent_class)->finalize(object);
+}
+
+static void
+nm_auth_subject_class_init(NMAuthSubjectClass *config_class)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS(config_class);
+
+    object_class->get_property = get_property;
+    object_class->set_property = set_property;
+    object_class->constructed  = constructed;
+    object_class->finalize     = finalize;
+
+    g_object_class_install_property(
+        object_class,
+        PROP_SUBJECT_TYPE,
+        g_param_spec_int(NM_AUTH_SUBJECT_SUBJECT_TYPE,
+                         "",
+                         "",
+                         NM_AUTH_SUBJECT_TYPE_INVALID,
+                         NM_AUTH_SUBJECT_TYPE_UNIX_SESSION,
+                         NM_AUTH_SUBJECT_TYPE_INVALID,
+                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+    g_object_class_install_property(
+        object_class,
+        PROP_UNIX_PROCESS_DBUS_SENDER,
+        g_param_spec_string(NM_AUTH_SUBJECT_UNIX_PROCESS_DBUS_SENDER,
+                            "",
+                            "",
+                            NULL,
+                            G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+    g_object_class_install_property(
+        object_class,
+        PROP_UNIX_PROCESS_PID,
+        g_param_spec_ulong(NM_AUTH_SUBJECT_UNIX_PROCESS_PID,
+                           "",
+                           "",
+                           0,
+                           G_MAXULONG,
+                           G_MAXULONG,
+                           G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+    g_object_class_install_property(
+        object_class,
+        PROP_UNIX_PROCESS_UID,
+        g_param_spec_ulong(NM_AUTH_SUBJECT_UNIX_PROCESS_UID,
+                           "",
+                           "",
+                           0,
+                           G_MAXULONG,
+                           G_MAXULONG,
+                           G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+    g_object_class_install_property(
+        object_class,
+        PROP_UNIX_SESSION_ID,
+        g_param_spec_string(NM_AUTH_SUBJECT_UNIX_SESSION_ID,
+                            "",
+                            "",
+                            NULL,
+                            G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+}
diff --git a/src/libnm-core-aux-intern/nm-auth-subject.h b/src/libnm-core-aux-intern/nm-auth-subject.h
new file mode 100644
index 00000000..2c9c4f71
--- /dev/null
+++ b/src/libnm-core-aux-intern/nm-auth-subject.h
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2013 Red Hat, Inc.
+ */
+
+#ifndef __NETWORKMANAGER_AUTH_SUBJECT_H__
+#define __NETWORKMANAGER_AUTH_SUBJECT_H__
+
+#define NM_TYPE_AUTH_SUBJECT (nm_auth_subject_get_type())
+#define NM_AUTH_SUBJECT(obj) \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_AUTH_SUBJECT, NMAuthSubject))
+#define NM_AUTH_SUBJECT_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_AUTH_SUBJECT, NMAuthSubjectClass))
+#define NM_IS_AUTH_SUBJECT(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_AUTH_SUBJECT))
+#define NM_IS_AUTH_SUBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_AUTH_SUBJECT))
+#define NM_AUTH_SUBJECT_GET_CLASS(obj) \
+    (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_AUTH_SUBJECT, NMAuthSubjectClass))
+
+typedef enum {
+    NM_AUTH_SUBJECT_TYPE_INVALID      = 0,
+    NM_AUTH_SUBJECT_TYPE_INTERNAL     = 1,
+    NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS = 2,
+    NM_AUTH_SUBJECT_TYPE_UNIX_SESSION = 4,
+} NMAuthSubjectType;
+
+#define NM_AUTH_SUBJECT_SUBJECT_TYPE             "subject-type"
+#define NM_AUTH_SUBJECT_UNIX_PROCESS_DBUS_SENDER "unix-process-dbus-sender"
+#define NM_AUTH_SUBJECT_UNIX_PROCESS_PID         "unix-process-pid"
+#define NM_AUTH_SUBJECT_UNIX_PROCESS_UID         "unix-process-uid"
+#define NM_AUTH_SUBJECT_UNIX_SESSION_ID          "unix-session-id"
+
+typedef struct _NMAuthSubjectClass NMAuthSubjectClass;
+typedef struct _NMAuthSubject      NMAuthSubject;
+
+GType nm_auth_subject_get_type(void);
+
+NMAuthSubject *nm_auth_subject_new_internal(void);
+
+NMAuthSubject *nm_auth_subject_new_unix_session(const char *session_id);
+
+NMAuthSubject *nm_auth_subject_new_unix_process(const char *dbus_sender, gulong pid, gulong uid);
+
+NMAuthSubject *nm_auth_subject_new_unix_process_self(void);
+
+NMAuthSubjectType nm_auth_subject_get_subject_type(NMAuthSubject *subject);
+
+gulong nm_auth_subject_get_unix_process_pid(NMAuthSubject *subject);
+
+const char *nm_auth_subject_get_unix_process_dbus_sender(NMAuthSubject *subject);
+
+gulong nm_auth_subject_get_unix_process_uid(NMAuthSubject *subject);
+
+const char *nm_auth_subject_get_unix_session_id(NMAuthSubject *subject);
+
+const char *nm_auth_subject_to_string(NMAuthSubject *self, char *buf, gsize buf_len);
+
+GVariant *nm_auth_subject_unix_to_polkit_gvariant(NMAuthSubject *self);
+
+#endif /* __NETWORKMANAGER_AUTH_SUBJECT_H__ */
diff --git a/src/libnm-core-aux-intern/nm-common-macros.h b/src/libnm-core-aux-intern/nm-common-macros.h
new file mode 100644
index 00000000..c452b7d3
--- /dev/null
+++ b/src/libnm-core-aux-intern/nm-common-macros.h
@@ -0,0 +1,65 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2016 Red Hat, Inc.
+ */
+
+#ifndef __NM_COMMON_MACROS_H__
+#define __NM_COMMON_MACROS_H__
+
+/*****************************************************************************/
+
+#define NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK \
+    "org.freedesktop.NetworkManager.enable-disable-network"
+#define NM_AUTH_PERMISSION_SLEEP_WAKE          "org.freedesktop.NetworkManager.sleep-wake"
+#define NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI "org.freedesktop.NetworkManager.enable-disable-wifi"
+#define NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN "org.freedesktop.NetworkManager.enable-disable-wwan"
+#define NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX \
+    "org.freedesktop.NetworkManager.enable-disable-wimax"
+#define NM_AUTH_PERMISSION_NETWORK_CONTROL "org.freedesktop.NetworkManager.network-control"
+#define NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED \
+    "org.freedesktop.NetworkManager.wifi.share.protected"
+#define NM_AUTH_PERMISSION_WIFI_SHARE_OPEN "org.freedesktop.NetworkManager.wifi.share.open"
+#define NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM \
+    "org.freedesktop.NetworkManager.settings.modify.system"
+#define NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN "org.freedesktop.NetworkManager.settings.modify.own"
+#define NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME \
+    "org.freedesktop.NetworkManager.settings.modify.hostname"
+#define NM_AUTH_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS \
+    "org.freedesktop.NetworkManager.settings.modify.global-dns"
+#define NM_AUTH_PERMISSION_RELOAD              "org.freedesktop.NetworkManager.reload"
+#define NM_AUTH_PERMISSION_CHECKPOINT_ROLLBACK "org.freedesktop.NetworkManager.checkpoint-rollback"
+#define NM_AUTH_PERMISSION_ENABLE_DISABLE_STATISTICS \
+    "org.freedesktop.NetworkManager.enable-disable-statistics"
+#define NM_AUTH_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK \
+    "org.freedesktop.NetworkManager.enable-disable-connectivity-check"
+#define NM_AUTH_PERMISSION_WIFI_SCAN "org.freedesktop.NetworkManager.wifi.scan"
+
+#define NM_CLONED_MAC_PRESERVE  "preserve"
+#define NM_CLONED_MAC_PERMANENT "permanent"
+#define NM_CLONED_MAC_RANDOM    "random"
+#define NM_CLONED_MAC_STABLE    "stable"
+
+static inline gboolean
+NM_CLONED_MAC_IS_SPECIAL(const char *str)
+{
+    return NM_IN_STRSET(str,
+                        NM_CLONED_MAC_PRESERVE,
+                        NM_CLONED_MAC_PERMANENT,
+                        NM_CLONED_MAC_RANDOM,
+                        NM_CLONED_MAC_STABLE);
+}
+
+#define NM_IAID_MAC      "mac"
+#define NM_IAID_PERM_MAC "perm-mac"
+#define NM_IAID_IFNAME   "ifname"
+#define NM_IAID_STABLE   "stable"
+
+#define NM_CONNECTION_MUD_URL_NONE "none"
+
+static inline gboolean
+NM_IAID_IS_SPECIAL(const char *str)
+{
+    return NM_IN_STRSET(str, NM_IAID_MAC, NM_IAID_PERM_MAC, NM_IAID_IFNAME, NM_IAID_STABLE);
+}
+
+#endif /* __NM_COMMON_MACROS_H__ */
diff --git a/src/libnm-core-aux-intern/nm-libnm-core-utils.c b/src/libnm-core-aux-intern/nm-libnm-core-utils.c
new file mode 100644
index 00000000..e53f840a
--- /dev/null
+++ b/src/libnm-core-aux-intern/nm-libnm-core-utils.c
@@ -0,0 +1,360 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "libnm-glib-aux/nm-default-glib-i18n-lib.h"
+
+#include "nm-libnm-core-utils.h"
+
+#include <linux/rtnetlink.h>
+
+#include "nm-common-macros.h"
+#include "nm-errors.h"
+
+/*****************************************************************************/
+
+const char **
+nm_utils_bond_option_arp_ip_targets_split(const char *arp_ip_target)
+{
+    return nm_utils_strsplit_set_full(arp_ip_target, ",", NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP);
+}
+
+void
+_nm_setting_bond_remove_options_miimon(NMSettingBond *s_bond)
+{
+    g_return_if_fail(NM_IS_SETTING_BOND(s_bond));
+
+    nm_setting_bond_remove_option(s_bond, NM_SETTING_BOND_OPTION_MIIMON);
+    nm_setting_bond_remove_option(s_bond, NM_SETTING_BOND_OPTION_UPDELAY);
+    nm_setting_bond_remove_option(s_bond, NM_SETTING_BOND_OPTION_DOWNDELAY);
+    nm_setting_bond_remove_option(s_bond, NM_SETTING_BOND_OPTION_PEER_NOTIF_DELAY);
+}
+
+void
+_nm_setting_bond_remove_options_arp_interval(NMSettingBond *s_bond)
+{
+    g_return_if_fail(NM_IS_SETTING_BOND(s_bond));
+
+    nm_setting_bond_remove_option(s_bond, NM_SETTING_BOND_OPTION_ARP_INTERVAL);
+    nm_setting_bond_remove_option(s_bond, NM_SETTING_BOND_OPTION_ARP_IP_TARGET);
+}
+
+/*****************************************************************************/
+
+NM_UTILS_STRING_TABLE_LOOKUP_DEFINE(
+    _nm_setting_bond_mode_from_string,
+    NMBondMode,
+    {
+        G_STATIC_ASSERT_EXPR(_NM_BOND_MODE_NUM <= 9);
+
+        if (name && name[0] < '0' + _NM_BOND_MODE_NUM && name[0] >= '0' && name[1] == '\0') {
+            return name[0] - '0';
+        }
+    },
+    { return NM_BOND_MODE_UNKNOWN; },
+    {"802.3ad", NM_BOND_MODE_8023AD},
+    {"active-backup", NM_BOND_MODE_ACTIVEBACKUP},
+    {"balance-alb", NM_BOND_MODE_ALB},
+    {"balance-rr", NM_BOND_MODE_ROUNDROBIN},
+    {"balance-tlb", NM_BOND_MODE_TLB},
+    {"balance-xor", NM_BOND_MODE_XOR},
+    {"broadcast", NM_BOND_MODE_BROADCAST}, );
+
+const char *
+_nm_setting_bond_mode_to_string(int mode)
+{
+    static const char *const modes[] = {
+        [NM_BOND_MODE_8023AD]       = "802.3ad",
+        [NM_BOND_MODE_ACTIVEBACKUP] = "active-backup",
+        [NM_BOND_MODE_ALB]          = "balance-alb",
+        [NM_BOND_MODE_BROADCAST]    = "broadcast",
+        [NM_BOND_MODE_ROUNDROBIN]   = "balance-rr",
+        [NM_BOND_MODE_TLB]          = "balance-tlb",
+        [NM_BOND_MODE_XOR]          = "balance-xor",
+    };
+
+    G_STATIC_ASSERT(G_N_ELEMENTS(modes) == _NM_BOND_MODE_NUM);
+
+    if (NM_MORE_ASSERT_ONCE(5)) {
+        char       sbuf[100];
+        int        i;
+        NMBondMode m;
+
+        for (i = 0; i < (int) G_N_ELEMENTS(modes); i++) {
+            nm_assert(modes[i]);
+            nm_assert(i == _nm_setting_bond_mode_from_string(modes[i]));
+            nm_assert(i == _nm_setting_bond_mode_from_string(nm_sprintf_buf(sbuf, "%d", i)));
+        }
+        nm_assert(NM_BOND_MODE_UNKNOWN == _nm_setting_bond_mode_from_string(NULL));
+        nm_assert(NM_BOND_MODE_UNKNOWN == _nm_setting_bond_mode_from_string(""));
+        for (i = -2; i < ((int) G_N_ELEMENTS(modes)) + 20; i++) {
+            if (i < 0 || i >= G_N_ELEMENTS(modes))
+                m = NM_BOND_MODE_UNKNOWN;
+            else
+                m = i;
+            nm_assert(m == _nm_setting_bond_mode_from_string(nm_sprintf_buf(sbuf, "%d", i)));
+        }
+    }
+
+    if (mode >= 0 && mode < (int) G_N_ELEMENTS(modes))
+        return modes[mode];
+    return NULL;
+}
+
+/*****************************************************************************/
+
+gboolean
+nm_utils_vlan_priority_map_parse_str(NMVlanPriorityMap map_type,
+                                     const char *      str,
+                                     gboolean          allow_wildcard_to,
+                                     guint32 *         out_from,
+                                     guint32 *         out_to,
+                                     gboolean *        out_has_wildcard_to)
+{
+    const char *s2;
+    gint64      v1, v2;
+
+    nm_assert(str);
+
+    s2 = strchr(str, ':');
+
+    if (!s2) {
+        if (!allow_wildcard_to)
+            return FALSE;
+        v1 = _nm_utils_ascii_str_to_int64(str, 10, 0, G_MAXUINT32, -1);
+        v2 = -1;
+    } else {
+        gs_free char *s1_free = NULL;
+        gsize         s1_len  = (s2 - str);
+
+        s2 = nm_str_skip_leading_spaces(&s2[1]);
+        if (s2[0] == '\0' || (s2[0] == '*' && NM_STRCHAR_ALL(&s2[1], ch, g_ascii_isspace(ch)))) {
+            if (!allow_wildcard_to)
+                return FALSE;
+            v2 = -1;
+        } else {
+            v2 = _nm_utils_ascii_str_to_int64(s2, 10, 0, G_MAXUINT32, -1);
+            if (v2 < 0 || (guint32) v2 > nm_utils_vlan_priority_map_get_max_prio(map_type, FALSE))
+                return FALSE;
+        }
+
+        v1 = _nm_utils_ascii_str_to_int64(nm_strndup_a(100, str, s1_len, &s1_free),
+                                          10,
+                                          0,
+                                          G_MAXUINT32,
+                                          -1);
+    }
+
+    if (v1 < 0 || (guint32) v1 > nm_utils_vlan_priority_map_get_max_prio(map_type, TRUE))
+        return FALSE;
+
+    NM_SET_OUT(out_from, v1);
+    NM_SET_OUT(out_to, v2 < 0 ? 0u : (guint) v2);
+    NM_SET_OUT(out_has_wildcard_to, v2 < 0);
+    return TRUE;
+}
+
+/*****************************************************************************/
+
+const char *const nm_auth_permission_names_by_idx[NM_CLIENT_PERMISSION_LAST] = {
+    [NM_CLIENT_PERMISSION_CHECKPOINT_ROLLBACK - 1] = NM_AUTH_PERMISSION_CHECKPOINT_ROLLBACK,
+    [NM_CLIENT_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK - 1] =
+        NM_AUTH_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK,
+    [NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK - 1] = NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK,
+    [NM_CLIENT_PERMISSION_ENABLE_DISABLE_STATISTICS - 1] =
+        NM_AUTH_PERMISSION_ENABLE_DISABLE_STATISTICS,
+    [NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIFI - 1]  = NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI,
+    [NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIMAX - 1] = NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX,
+    [NM_CLIENT_PERMISSION_ENABLE_DISABLE_WWAN - 1]  = NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN,
+    [NM_CLIENT_PERMISSION_NETWORK_CONTROL - 1]      = NM_AUTH_PERMISSION_NETWORK_CONTROL,
+    [NM_CLIENT_PERMISSION_RELOAD - 1]               = NM_AUTH_PERMISSION_RELOAD,
+    [NM_CLIENT_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS - 1] =
+        NM_AUTH_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS,
+    [NM_CLIENT_PERMISSION_SETTINGS_MODIFY_HOSTNAME - 1] =
+        NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME,
+    [NM_CLIENT_PERMISSION_SETTINGS_MODIFY_OWN - 1]    = NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN,
+    [NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM - 1] = NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM,
+    [NM_CLIENT_PERMISSION_SLEEP_WAKE - 1]             = NM_AUTH_PERMISSION_SLEEP_WAKE,
+    [NM_CLIENT_PERMISSION_WIFI_SCAN - 1]              = NM_AUTH_PERMISSION_WIFI_SCAN,
+    [NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN - 1]        = NM_AUTH_PERMISSION_WIFI_SHARE_OPEN,
+    [NM_CLIENT_PERMISSION_WIFI_SHARE_PROTECTED - 1]   = NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED,
+};
+
+const NMClientPermission nm_auth_permission_sorted[NM_CLIENT_PERMISSION_LAST] = {
+    NM_CLIENT_PERMISSION_CHECKPOINT_ROLLBACK,
+    NM_CLIENT_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK,
+    NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK,
+    NM_CLIENT_PERMISSION_ENABLE_DISABLE_STATISTICS,
+    NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIFI,
+    NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIMAX,
+    NM_CLIENT_PERMISSION_ENABLE_DISABLE_WWAN,
+    NM_CLIENT_PERMISSION_NETWORK_CONTROL,
+    NM_CLIENT_PERMISSION_RELOAD,
+    NM_CLIENT_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS,
+    NM_CLIENT_PERMISSION_SETTINGS_MODIFY_HOSTNAME,
+    NM_CLIENT_PERMISSION_SETTINGS_MODIFY_OWN,
+    NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM,
+    NM_CLIENT_PERMISSION_SLEEP_WAKE,
+    NM_CLIENT_PERMISSION_WIFI_SCAN,
+    NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN,
+    NM_CLIENT_PERMISSION_WIFI_SHARE_PROTECTED,
+};
+
+const char *
+nm_auth_permission_to_string(NMClientPermission permission)
+{
+    if (permission < 1)
+        return NULL;
+    if (permission > NM_CLIENT_PERMISSION_LAST)
+        return NULL;
+    return nm_auth_permission_names_by_idx[permission - 1];
+}
+
+#define AUTH_PERMISSION_PREFIX "org.freedesktop.NetworkManager."
+
+static int
+_nm_auth_permission_from_string_cmp(gconstpointer a, gconstpointer b, gpointer user_data)
+{
+    const NMClientPermission *const p      = a;
+    const char *const               needle = b;
+    const char *                    ss     = nm_auth_permission_names_by_idx[*p - 1];
+
+    nm_assert(NM_STR_HAS_PREFIX(ss, AUTH_PERMISSION_PREFIX));
+    nm_assert(ss[NM_STRLEN(AUTH_PERMISSION_PREFIX)] != '\0');
+
+    return strcmp(&ss[NM_STRLEN(AUTH_PERMISSION_PREFIX)], needle);
+}
+
+NMClientPermission
+nm_auth_permission_from_string(const char *str)
+{
+    gssize idx;
+
+    if (!str)
+        return NM_CLIENT_PERMISSION_NONE;
+
+    if (!NM_STR_HAS_PREFIX(str, AUTH_PERMISSION_PREFIX))
+        return NM_CLIENT_PERMISSION_NONE;
+    idx = nm_utils_array_find_binary_search(nm_auth_permission_sorted,
+                                            sizeof(nm_auth_permission_sorted[0]),
+                                            G_N_ELEMENTS(nm_auth_permission_sorted),
+                                            &str[NM_STRLEN(AUTH_PERMISSION_PREFIX)],
+                                            _nm_auth_permission_from_string_cmp,
+                                            NULL);
+    if (idx < 0)
+        return NM_CLIENT_PERMISSION_NONE;
+    return nm_auth_permission_sorted[idx];
+}
+
+/*****************************************************************************/
+
+NMClientPermissionResult
+nm_client_permission_result_from_string(const char *nm)
+{
+    if (!nm)
+        return NM_CLIENT_PERMISSION_RESULT_UNKNOWN;
+    if (nm_streq(nm, "yes"))
+        return NM_CLIENT_PERMISSION_RESULT_YES;
+    if (nm_streq(nm, "no"))
+        return NM_CLIENT_PERMISSION_RESULT_NO;
+    if (nm_streq(nm, "auth"))
+        return NM_CLIENT_PERMISSION_RESULT_AUTH;
+    return NM_CLIENT_PERMISSION_RESULT_UNKNOWN;
+}
+
+const char *
+nm_client_permission_result_to_string(NMClientPermissionResult permission)
+{
+    switch (permission) {
+    case NM_CLIENT_PERMISSION_RESULT_YES:
+        return "yes";
+    case NM_CLIENT_PERMISSION_RESULT_NO:
+        return "no";
+    case NM_CLIENT_PERMISSION_RESULT_AUTH:
+        return "auth";
+    case NM_CLIENT_PERMISSION_RESULT_UNKNOWN:
+        return "unknown";
+    }
+    nm_assert_not_reached();
+    return NULL;
+}
+
+gboolean
+nm_utils_validate_dhcp4_vendor_class_id(const char *vci, GError **error)
+{
+    const char *  bin;
+    gsize         unescaped_len;
+    gs_free char *to_free = NULL;
+
+    g_return_val_if_fail(!error || !(*error), FALSE);
+    g_return_val_if_fail(vci, FALSE);
+
+    if (vci[0] == '\0') {
+        g_set_error_literal(error,
+                            NM_CONNECTION_ERROR,
+                            NM_CONNECTION_ERROR_INVALID_PROPERTY,
+                            _("property cannot be an empty string"));
+        g_prefix_error(error,
+                       "%s.%s: ",
+                       NM_SETTING_IP4_CONFIG_SETTING_NAME,
+                       NM_SETTING_IP4_CONFIG_DHCP_VENDOR_CLASS_IDENTIFIER);
+        return FALSE;
+    }
+
+    bin = nm_utils_buf_utf8safe_unescape(vci,
+                                         NM_UTILS_STR_UTF8_SAFE_FLAG_NONE,
+                                         &unescaped_len,
+                                         (gpointer *) &to_free);
+    /* a DHCP option cannot be longer than 255 bytes */
+    if (unescaped_len > 255) {
+        g_set_error_literal(error,
+                            NM_CONNECTION_ERROR,
+                            NM_CONNECTION_ERROR_INVALID_PROPERTY,
+                            _("property cannot be longer than 255 bytes"));
+        g_prefix_error(error,
+                       "%s.%s: ",
+                       NM_SETTING_IP4_CONFIG_SETTING_NAME,
+                       NM_SETTING_IP4_CONFIG_DHCP_VENDOR_CLASS_IDENTIFIER);
+        return FALSE;
+    }
+    if (strlen(bin) != unescaped_len) {
+        g_set_error_literal(error,
+                            NM_CONNECTION_ERROR,
+                            NM_CONNECTION_ERROR_INVALID_PROPERTY,
+                            _("property cannot contain any nul bytes"));
+        g_prefix_error(error,
+                       "%s.%s: ",
+                       NM_SETTING_IP4_CONFIG_SETTING_NAME,
+                       NM_SETTING_IP4_CONFIG_DHCP_VENDOR_CLASS_IDENTIFIER);
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+gboolean
+nm_settings_connection_validate_permission_user(const char *item, gssize len)
+{
+    gsize l;
+
+    if (!item)
+        return FALSE;
+
+    if (len < 0) {
+        nm_assert(len == -1);
+        l = strlen(item);
+    } else
+        l = (gsize) len;
+
+    if (l == 0)
+        return FALSE;
+
+    if (!g_utf8_validate(item, l, NULL))
+        return FALSE;
+
+    if (l >= 100)
+        return FALSE;
+
+    if (memchr(item, ':', l))
+        return FALSE;
+
+    return TRUE;
+}
diff --git a/src/libnm-core-aux-intern/nm-libnm-core-utils.h b/src/libnm-core-aux-intern/nm-libnm-core-utils.h
new file mode 100644
index 00000000..e0a6aaf1
--- /dev/null
+++ b/src/libnm-core-aux-intern/nm-libnm-core-utils.h
@@ -0,0 +1,169 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#ifndef __NM_LIBNM_SHARED_UTILS_H__
+#define __NM_LIBNM_SHARED_UTILS_H__
+
+/****************************************************************************/
+
+#include "nm-setting-bond.h"
+#include "nm-setting-bridge.h"
+#include "nm-setting-connection.h"
+#include "nm-setting-ip-config.h"
+#include "nm-setting-ip4-config.h"
+#include "nm-setting-ip6-config.h"
+#include "nm-setting-sriov.h"
+#include "nm-setting-team.h"
+#include "nm-setting-vlan.h"
+#include "nm-setting-wireguard.h"
+
+/****************************************************************************/
+
+#define nm_auto_unref_ip_address nm_auto(_nm_ip_address_unref)
+NM_AUTO_DEFINE_FCN0(NMIPAddress *, _nm_ip_address_unref, nm_ip_address_unref);
+
+#define nm_auto_unref_ip_route nm_auto(_nm_auto_unref_ip_route)
+NM_AUTO_DEFINE_FCN0(NMIPRoute *, _nm_auto_unref_ip_route, nm_ip_route_unref);
+
+#define nm_auto_unref_ip_routing_rule nm_auto(_nm_auto_unref_ip_routing_rule)
+NM_AUTO_DEFINE_FCN0(NMIPRoutingRule *, _nm_auto_unref_ip_routing_rule, nm_ip_routing_rule_unref);
+
+#define nm_auto_unref_sriov_vf nm_auto(_nm_auto_unref_sriov_vf)
+NM_AUTO_DEFINE_FCN0(NMSriovVF *, _nm_auto_unref_sriov_vf, nm_sriov_vf_unref);
+
+#define nm_auto_unref_tc_qdisc nm_auto(_nm_auto_unref_tc_qdisc)
+NM_AUTO_DEFINE_FCN0(NMTCQdisc *, _nm_auto_unref_tc_qdisc, nm_tc_qdisc_unref);
+
+#define nm_auto_unref_tc_tfilter nm_auto(_nm_auto_unref_tc_tfilter)
+NM_AUTO_DEFINE_FCN0(NMTCTfilter *, _nm_auto_unref_tc_tfilter, nm_tc_tfilter_unref);
+
+#define nm_auto_unref_tc_action nm_auto(_nm_auto_unref_tc_action)
+NM_AUTO_DEFINE_FCN0(NMTCAction *, _nm_auto_unref_tc_action, nm_tc_action_unref);
+
+#define nm_auto_unref_bridge_vlan nm_auto(_nm_auto_unref_bridge_vlan)
+NM_AUTO_DEFINE_FCN0(NMBridgeVlan *, _nm_auto_unref_bridge_vlan, nm_bridge_vlan_unref);
+
+#define nm_auto_unref_team_link_watcher nm_auto(_nm_auto_unref_team_link_watcher)
+NM_AUTO_DEFINE_FCN0(NMTeamLinkWatcher *,
+                    _nm_auto_unref_team_link_watcher,
+                    nm_team_link_watcher_unref);
+
+#define nm_auto_unref_wgpeer nm_auto(_nm_auto_unref_wgpeer)
+NM_AUTO_DEFINE_FCN0(NMWireGuardPeer *, _nm_auto_unref_wgpeer, nm_wireguard_peer_unref);
+
+/****************************************************************************/
+
+const char **nm_utils_bond_option_arp_ip_targets_split(const char *arp_ip_target);
+
+void _nm_setting_bond_remove_options_miimon(NMSettingBond *s_bond);
+void _nm_setting_bond_remove_options_arp_interval(NMSettingBond *s_bond);
+
+typedef enum {
+    NM_BOND_MODE_UNKNOWN = -1,
+
+    /* The numeric values correspond to kernel's numbering of the modes. */
+    NM_BOND_MODE_ROUNDROBIN   = 0,
+    NM_BOND_MODE_ACTIVEBACKUP = 1,
+    NM_BOND_MODE_XOR          = 2,
+    NM_BOND_MODE_BROADCAST    = 3,
+    NM_BOND_MODE_8023AD       = 4,
+    NM_BOND_MODE_TLB          = 5,
+    NM_BOND_MODE_ALB          = 6,
+
+    _NM_BOND_MODE_NUM,
+} NMBondMode;
+
+NMBondMode _nm_setting_bond_mode_from_string(const char *str);
+
+const char *_nm_setting_bond_mode_to_string(int mode);
+
+gboolean _nm_setting_bond_validate_option(const char *name, const char *value, GError **error);
+
+/*****************************************************************************/
+
+static inline guint32
+nm_utils_vlan_priority_map_get_max_prio(NMVlanPriorityMap map, gboolean from)
+{
+    if (map == NM_VLAN_INGRESS_MAP) {
+        return from ? 7u /* MAX_8021P_PRIO */
+                    : (guint32) G_MAXUINT32 /* MAX_SKB_PRIO */;
+    }
+    nm_assert(map == NM_VLAN_EGRESS_MAP);
+    return from ? (guint32) G_MAXUINT32 /* MAX_SKB_PRIO */
+                : 7u /* MAX_8021P_PRIO */;
+}
+
+gboolean nm_utils_vlan_priority_map_parse_str(NMVlanPriorityMap map_type,
+                                              const char *      str,
+                                              gboolean          allow_wildcard_to,
+                                              guint32 *         out_from,
+                                              guint32 *         out_to,
+                                              gboolean *        out_has_wildcard_to);
+
+/*****************************************************************************/
+
+#define _NM_DEVICE_INTERFACE_FLAG_ALL                                                          \
+    ((NMDeviceInterfaceFlags) (NM_DEVICE_INTERFACE_FLAG_UP | NM_DEVICE_INTERFACE_FLAG_LOWER_UP \
+                               | NM_DEVICE_INTERFACE_FLAG_CARRIER                              \
+                               | NM_DEVICE_INTERFACE_FLAG_PROMISC                              \
+                               | NM_DEVICE_INTERFACE_FLAG_LLDP_CLIENT_ENABLED))
+
+/*****************************************************************************/
+
+#define NM_OVS_EXTERNAL_ID_NM_PREFIX          "NM."
+#define NM_OVS_EXTERNAL_ID_NM_CONNECTION_UUID "NM.connection.uuid"
+
+/*****************************************************************************/
+
+static inline int
+nm_setting_ip_config_get_addr_family(NMSettingIPConfig *s_ip)
+{
+    if (NM_IS_SETTING_IP4_CONFIG(s_ip))
+        return AF_INET;
+    if (NM_IS_SETTING_IP6_CONFIG(s_ip))
+        return AF_INET6;
+    g_return_val_if_reached(AF_UNSPEC);
+}
+
+/*****************************************************************************/
+
+/* The maximum MTU for infiniband.
+ *
+ * This is both in transport-mode "datagram" and "connected"
+ * and they both have the same maximum define.
+ *
+ * Note that in the past, MTU in "datagram" mode was restricted
+ * to 2044 bytes. That is no longer the case and we accept large
+ * MTUs.
+ *
+ * This define is the maxiumum for the MTU in a connection profile (the
+ * setting). Whether large MTUs can be configured later (at activation time)
+ * depends on other factors. */
+#define NM_INFINIBAND_MAX_MTU ((guint) 65520)
+
+/*****************************************************************************/
+
+#define _NM_CAPABILITY_MAX NM_CAPABILITY_OVS
+
+/*****************************************************************************/
+
+extern const char *const        nm_auth_permission_names_by_idx[NM_CLIENT_PERMISSION_LAST];
+extern const NMClientPermission nm_auth_permission_sorted[NM_CLIENT_PERMISSION_LAST];
+
+const char *       nm_auth_permission_to_string(NMClientPermission permission);
+NMClientPermission nm_auth_permission_from_string(const char *str);
+
+/*****************************************************************************/
+
+NMClientPermissionResult nm_client_permission_result_from_string(const char *nm);
+const char *             nm_client_permission_result_to_string(NMClientPermissionResult permission);
+
+gboolean nm_utils_validate_dhcp4_vendor_class_id(const char *vci, GError **error);
+
+/*****************************************************************************/
+
+#define NM_SETTINGS_CONNECTION_PERMISSION_USER        "user"
+#define NM_SETTINGS_CONNECTION_PERMISSION_USER_PREFIX "user:"
+
+gboolean nm_settings_connection_validate_permission_user(const char *item, gssize len);
+
+#endif /* __NM_LIBNM_SHARED_UTILS_H__ */