summary refs log tree commit diff
path: root/src/libnm-glib-aux
diff options
context:
space:
mode:
Diffstat (limited to 'src/libnm-glib-aux')
-rw-r--r--src/libnm-glib-aux/nm-dbus-aux.c2
-rw-r--r--src/libnm-glib-aux/nm-dedup-multi.c4
-rw-r--r--src/libnm-glib-aux/nm-hash-utils.h20
-rw-r--r--src/libnm-glib-aux/nm-inet-utils.h6
-rw-r--r--src/libnm-glib-aux/nm-io-utils.c4
-rw-r--r--src/libnm-glib-aux/nm-json-aux.c2
-rw-r--r--src/libnm-glib-aux/nm-keyfile-aux.c19
-rw-r--r--src/libnm-glib-aux/nm-keyfile-aux.h2
-rw-r--r--src/libnm-glib-aux/nm-macros-internal.h94
-rw-r--r--src/libnm-glib-aux/nm-prioq.c6
-rw-r--r--src/libnm-glib-aux/nm-random-utils.c448
-rw-r--r--src/libnm-glib-aux/nm-random-utils.h18
-rw-r--r--src/libnm-glib-aux/nm-secret-utils.h12
-rw-r--r--src/libnm-glib-aux/nm-shared-utils.c74
-rw-r--r--src/libnm-glib-aux/nm-shared-utils.h50
-rw-r--r--src/libnm-glib-aux/nm-test-utils.h2
-rw-r--r--src/libnm-glib-aux/nm-uuid.h4
-rw-r--r--src/libnm-glib-aux/nm-value-type.h4
-rw-r--r--src/libnm-glib-aux/tests/test-json-aux.c8
-rw-r--r--src/libnm-glib-aux/tests/test-shared-general.c27
20 files changed, 260 insertions, 546 deletions
diff --git a/src/libnm-glib-aux/nm-dbus-aux.c b/src/libnm-glib-aux/nm-dbus-aux.c
index 5c4dbc49..1be4047e 100644
--- a/src/libnm-glib-aux/nm-dbus-aux.c
+++ b/src/libnm-glib-aux/nm-dbus-aux.c
@@ -382,7 +382,7 @@ nm_dbus_call(GBusType            bus_type,
     CallAsyncInfo *info;
 
     info  = g_new(CallAsyncInfo, 1);
-    *info = (CallAsyncInfo){
+    *info = (CallAsyncInfo) {
         .bus_name       = g_strdup(bus_name),
         .object_path    = g_strdup(object_path),
         .interface_name = g_strdup(interface_name),
diff --git a/src/libnm-glib-aux/nm-dedup-multi.c b/src/libnm-glib-aux/nm-dedup-multi.c
index cf2dba90..c80b17ce 100644
--- a/src/libnm-glib-aux/nm-dedup-multi.c
+++ b/src/libnm-glib-aux/nm-dedup-multi.c
@@ -54,7 +54,7 @@ nm_dedup_multi_idx_type_init(NMDedupMultiIdxType *idx_type, const NMDedupMultiId
     nm_assert(idx_type);
     nm_assert(klass);
 
-    *idx_type = (NMDedupMultiIdxType){
+    *idx_type = (NMDedupMultiIdxType) {
         .klass        = klass,
         .lst_idx_head = C_LIST_INIT(idx_type->lst_idx_head),
     };
@@ -1005,7 +1005,7 @@ nm_dedup_multi_index_new(void)
     NMDedupMultiIndex *self;
 
     self  = g_slice_new(NMDedupMultiIndex);
-    *self = (NMDedupMultiIndex){
+    *self = (NMDedupMultiIndex) {
         .ref_count   = 1,
         .idx_entries = g_hash_table_new((GHashFunc) _dict_idx_entries_hash,
                                         (GEqualFunc) _dict_idx_entries_equal),
diff --git a/src/libnm-glib-aux/nm-hash-utils.h b/src/libnm-glib-aux/nm-hash-utils.h
index 703c00a4..6d7cc271 100644
--- a/src/libnm-glib-aux/nm-hash-utils.h
+++ b/src/libnm-glib-aux/nm-hash-utils.h
@@ -12,7 +12,7 @@
 /*****************************************************************************/
 
 #define NM_HASH_SEED_16(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, aa, ab, ac, ad, ae, af) \
-    ((const guint8[16]){a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, aa, ab, ac, ad, ae, af})
+    ((const guint8[16]) {a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, aa, ab, ac, ad, ae, af})
 
 struct _nm_packed _nm_hash_seed_16_u64_data {
     guint64 s1;
@@ -29,11 +29,11 @@ G_STATIC_ASSERT(sizeof(struct _nm_hash_seed_16_u64_data) == sizeof(guint64) * 2)
  * This macro takes a u64 (in host-endianness) and returns a 16 byte seed
  * buffer. The number will be big endian encoded, to be architecture
  * independent. */
-#define NM_HASH_SEED_16_U64(u64)                              \
-    ((const guint8 *) ((gpointer)                             \
-                       & ((struct _nm_hash_seed_16_u64_data){ \
-                           .s1 = htobe64((u64)),              \
-                           .s2 = 0,                           \
+#define NM_HASH_SEED_16_U64(u64)                               \
+    ((const guint8 *) ((gpointer)                              \
+                       & ((struct _nm_hash_seed_16_u64_data) { \
+                           .s1 = htobe64((u64)),               \
+                           .s2 = 0,                            \
                        })))
 
 /*****************************************************************************/
@@ -212,10 +212,10 @@ nm_hash_update_str(NMHashState *state, const char *str)
 /* 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))))
+#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
diff --git a/src/libnm-glib-aux/nm-inet-utils.h b/src/libnm-glib-aux/nm-inet-utils.h
index 65ceeb2e..489d21dd 100644
--- a/src/libnm-glib-aux/nm-inet-utils.h
+++ b/src/libnm-glib-aux/nm-inet-utils.h
@@ -22,10 +22,7 @@ typedef struct _NMIPAddrTyped {
     gint8    addr_family;
 } NMIPAddrTyped;
 
-#define NM_IP_ADDR_INIT   \
-    {                     \
-        .addr_ptr = { 0 } \
-    }
+#define NM_IP_ADDR_INIT {.addr_ptr = {0}}
 
 #define _NM_IN6ADDR_INIT(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, aa, ab, ac, ad, ae, af) \
     {                                                                                    \
@@ -285,6 +282,7 @@ gboolean nm_ip6_addr_is_ula(const struct in6_addr *address);
 
 #define NM_IPV4LL_NETWORK   ((in_addr_t) htonl(0xA9FE0000lu)) /* 169.254.0.0 */
 #define NM_IPV4LL_NETMASK   ((in_addr_t) htonl(0xFFFF0000lu)) /* 255.255.0.0 */
+#define NM_IPV4LL_PREFIXLEN 16
 #define NM_IPV4LO_NETWORK   ((in_addr_t) htonl(0x7F000000lu)) /* 127.0.0.0 */
 #define NM_IPV4LO_NETMASK   ((in_addr_t) htonl(0xFF000000lu)) /* 255.0.0.0 */
 #define NM_IPV4LO_PREFIXLEN 8
diff --git a/src/libnm-glib-aux/nm-io-utils.c b/src/libnm-glib-aux/nm-io-utils.c
index ec016ed8..9443172b 100644
--- a/src/libnm-glib-aux/nm-io-utils.c
+++ b/src/libnm-glib-aux/nm-io-utils.c
@@ -683,7 +683,7 @@ nm_g_subprocess_terminate_in_background(GSubprocess *subprocess, int timeout_mse
     main_context = g_main_context_get_thread_default();
 
     term_data  = g_slice_new(SubprocessTerminateData);
-    *term_data = (SubprocessTerminateData){
+    *term_data = (SubprocessTerminateData) {
         .subprocess     = g_object_ref(subprocess),
         .timeout_source = NULL,
     };
@@ -845,7 +845,7 @@ nm_sd_notify(const char *state)
 
     /* systemd calls here fd_set_sndbuf(fd, SNDBUF_SIZE) .We don't bother. */
 
-    iovec = (struct iovec){
+    iovec = (struct iovec) {
         .iov_base = (gpointer) state,
         .iov_len  = strlen(state),
     };
diff --git a/src/libnm-glib-aux/nm-json-aux.c b/src/libnm-glib-aux/nm-json-aux.c
index 6216d93c..97172726 100644
--- a/src/libnm-glib-aux/nm-json-aux.c
+++ b/src/libnm-glib-aux/nm-json-aux.c
@@ -230,7 +230,7 @@ _nm_json_vt_internal_load(void)
 
 fail_symbol:
     dlclose(&handle);
-    *v = (NMJsonVtInternal){};
+    *v = (NMJsonVtInternal) {};
     return v;
 }
 
diff --git a/src/libnm-glib-aux/nm-keyfile-aux.c b/src/libnm-glib-aux/nm-keyfile-aux.c
index 20a4690f..42f4f8be 100644
--- a/src/libnm-glib-aux/nm-keyfile-aux.c
+++ b/src/libnm-glib-aux/nm-keyfile-aux.c
@@ -485,3 +485,22 @@ nm_key_file_db_prune(NMKeyFileDB *self,
         }
     }
 }
+
+void
+nm_key_file_add_group(GKeyFile *keyfile, const char *group)
+{
+    nm_assert(keyfile);
+    nm_assert(group);
+
+    /* You can only call this function if the group doesn't exist yet.
+     * Because, we are about to add a dummy key, so we would have to
+     * be sure that the key doesn't exist. */
+    nm_assert(!g_key_file_has_group(keyfile, group));
+
+    /* Ensure the group is present.
+     * There is no API for that, so add and remove a dummy key.
+     * For a profile it matters whether a setting is present or not,
+     * and we need to ensure that we persist the presence of the setting to keyfile*/
+    g_key_file_set_value(keyfile, group, ".X", "1");
+    g_key_file_remove_key(keyfile, group, ".X", NULL);
+}
diff --git a/src/libnm-glib-aux/nm-keyfile-aux.h b/src/libnm-glib-aux/nm-keyfile-aux.h
index 7ada4029..50cfdfcd 100644
--- a/src/libnm-glib-aux/nm-keyfile-aux.h
+++ b/src/libnm-glib-aux/nm-keyfile-aux.h
@@ -58,4 +58,6 @@ void nm_key_file_db_prune(NMKeyFileDB *self,
 
 /*****************************************************************************/
 
+void nm_key_file_add_group(GKeyFile *keyfile, const char *group);
+
 #endif /* __NM_KEYFILE_AUX_H__ */
diff --git a/src/libnm-glib-aux/nm-macros-internal.h b/src/libnm-glib-aux/nm-macros-internal.h
index 0b39271e..151e7a4f 100644
--- a/src/libnm-glib-aux/nm-macros-internal.h
+++ b/src/libnm-glib-aux/nm-macros-internal.h
@@ -218,40 +218,40 @@ NM_G_ERROR_MSG(GError *error)
 #if _NM_CC_SUPPORT_GENERIC
 #define _NM_CONSTCAST_FULL_1(type, obj_expr, obj) \
     (_Generic((obj_expr),                         \
-        const void *: ((const type *) (obj)),     \
-        void *: ((type *) (obj)),                 \
-        const type *: ((const type *) (obj)),     \
-        type *: ((type *) (obj))))
+         const void *: ((const type *) (obj)),    \
+         void *: ((type *) (obj)),                \
+         const type *: ((const type *) (obj)),    \
+         type *: ((type *) (obj))))
 #define _NM_CONSTCAST_FULL_2(type, obj_expr, obj, alias_type2) \
     (_Generic((obj_expr),                                      \
-        const void *: ((const type *) (obj)),                  \
-        void *: ((type *) (obj)),                              \
-        const alias_type2 *: ((const type *) (obj)),           \
-        alias_type2 *: ((type *) (obj)),                       \
-        const type *: ((const type *) (obj)),                  \
-        type *: ((type *) (obj))))
+         const void *: ((const type *) (obj)),                 \
+         void *: ((type *) (obj)),                             \
+         const alias_type2 *: ((const type *) (obj)),          \
+         alias_type2 *: ((type *) (obj)),                      \
+         const 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 type *) (obj)),                               \
-        void *: ((type *) (obj)),                                           \
-        const alias_type2 *: ((const type *) (obj)),                        \
-        alias_type2 *: ((type *) (obj)),                                    \
-        const alias_type3 *: ((const type *) (obj)),                        \
-        alias_type3 *: ((type *) (obj)),                                    \
-        const type *: ((const type *) (obj)),                               \
-        type *: ((type *) (obj))))
+         const void *: ((const type *) (obj)),                              \
+         void *: ((type *) (obj)),                                          \
+         const alias_type2 *: ((const type *) (obj)),                       \
+         alias_type2 *: ((type *) (obj)),                                   \
+         const alias_type3 *: ((const type *) (obj)),                       \
+         alias_type3 *: ((type *) (obj)),                                   \
+         const 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 type *) (obj)),                                            \
-        void *: ((type *) (obj)),                                                        \
-        const alias_type2 *: ((const type *) (obj)),                                     \
-        alias_type2 *: ((type *) (obj)),                                                 \
-        const alias_type3 *: ((const type *) (obj)),                                     \
-        alias_type3 *: ((type *) (obj)),                                                 \
-        const alias_type4 *: ((const type *) (obj)),                                     \
-        alias_type4 *: ((type *) (obj)),                                                 \
-        const type *: ((const type *) (obj)),                                            \
-        type *: ((type *) (obj))))
+         const void *: ((const type *) (obj)),                                           \
+         void *: ((type *) (obj)),                                                       \
+         const alias_type2 *: ((const type *) (obj)),                                    \
+         alias_type2 *: ((type *) (obj)),                                                \
+         const alias_type3 *: ((const type *) (obj)),                                    \
+         alias_type3 *: ((type *) (obj)),                                                \
+         const alias_type4 *: ((const type *) (obj)),                                    \
+         alias_type4 *: ((type *) (obj)),                                                \
+         const 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, ...) \
@@ -335,29 +335,29 @@ NM_G_ERROR_MSG(GError *error)
  * 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)))
+#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)))))
+#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
@@ -365,8 +365,8 @@ NM_G_ERROR_MSG(GError *error)
 /* 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 *)) \
+#define NM_MAKE_STRV(...)                                                                      \
+    ((const char *const[(sizeof(((const char *const[]) {__VA_ARGS__})) / sizeof(const char *)) \
                         + 1]){__VA_ARGS__})
 
 /*****************************************************************************/
diff --git a/src/libnm-glib-aux/nm-prioq.c b/src/libnm-glib-aux/nm-prioq.c
index e74b2b99..1b051644 100644
--- a/src/libnm-glib-aux/nm-prioq.c
+++ b/src/libnm-glib-aux/nm-prioq.c
@@ -57,7 +57,7 @@ nm_prioq_init(NMPrioq *q, GCompareFunc compare_func)
     nm_assert(q);
     nm_assert(compare_func);
 
-    *q = (NMPrioq){
+    *q = (NMPrioq) {
         ._priv =
             {
                 .compare_func      = compare_func,
@@ -76,7 +76,7 @@ nm_prioq_init_with_data(NMPrioq *q, GCompareDataFunc compare_func, gpointer comp
     nm_assert(q);
     nm_assert(compare_func);
 
-    *q = (NMPrioq){
+    *q = (NMPrioq) {
         ._priv =
             {
                 .compare_data_func = compare_func,
@@ -223,7 +223,7 @@ nm_prioq_put(NMPrioq *q, void *data, unsigned *idx)
 
     k = q->_priv.n_items++;
 
-    q->_priv.items[k] = (PrioqItem){
+    q->_priv.items[k] = (PrioqItem) {
         .data = data,
         .idx  = idx,
     };
diff --git a/src/libnm-glib-aux/nm-random-utils.c b/src/libnm-glib-aux/nm-random-utils.c
index bbc5536a..66c62251 100644
--- a/src/libnm-glib-aux/nm-random-utils.c
+++ b/src/libnm-glib-aux/nm-random-utils.c
@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 /*
  * Copyright (C) 2017 Red Hat, Inc.
+ * Copyright (C) 2025 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
  */
 
 #include "libnm-glib-aux/nm-default-glib-i18n-lib.h"
@@ -51,420 +52,85 @@ getrandom(void *buf, size_t buflen, unsigned flags)
 /*****************************************************************************/
 
 static ssize_t
-_getrandom(void *buf, size_t buflen, unsigned flags)
+getrandom_full(void *buf, size_t count, unsigned flags)
 {
-    static int have_getrandom = TRUE;
-    ssize_t    l;
-    int        errsv;
-
-    nm_assert(buflen > 0);
-
-    /* This calls getrandom() and either returns the positive
-     * success or an negative errno. ENOSYS means getrandom()
-     * call is not supported. That result is cached and we don't retry. */
-
-    if (!have_getrandom)
-        return -ENOSYS;
-
-    l = getrandom(buf, buflen, flags);
-    if (l > 0)
-        return l;
-    if (l == 0)
-        return -EIO;
-    errsv = errno;
-    if (errsv == ENOSYS)
-        have_getrandom = FALSE;
-    return -errsv;
-}
-
-static ssize_t
-_getrandom_insecure(void *buf, size_t buflen)
-{
-    static int have_grnd_insecure = TRUE;
-    ssize_t    l;
-
-    /* GRND_INSECURE was added recently. We catch EINVAL
-     * if kernel does not support the flag (and cache it). */
-
-    if (!have_grnd_insecure)
-        return -EINVAL;
-
-    l = _getrandom(buf, buflen, GRND_INSECURE);
-
-    if (l == -EINVAL)
-        have_grnd_insecure = FALSE;
-
-    return l;
+    ssize_t  ret;
+    uint8_t *p = buf;
+
+    do {
+        ret = getrandom(p, count, flags);
+        if (ret < 0 && errno == EINTR)
+            continue;
+        else if (ret < 0)
+            return ret;
+        p += ret;
+        count -= ret;
+    } while (count);
+    return 0;
 }
 
-static ssize_t
-_getrandom_best_effort(void *buf, size_t buflen)
-{
-    ssize_t l;
-
-    /* To get best-effort bytes, we would use GRND_INSECURE (and we try that
-     * first). However, not all kernel versions support that, so we fallback
-     * to GRND_NONBLOCK.
-     *
-     * Granted, this is called from a fallback path where we have no entropy
-     * already, it's unlikely that GRND_NONBLOCK would succeed. Still... */
-    l = _getrandom_insecure(buf, buflen);
-    if (l != -EINVAL)
-        return l;
-
-    return _getrandom(buf, buflen, GRND_NONBLOCK);
-}
-
-static int
-_random_check_entropy(gboolean block)
-{
-    static gboolean   seen_high_quality = FALSE;
-    nm_auto_close int fd                = -1;
-    int               r;
-
-    /* We come here because getrandom() gave ENOSYS. We will fallback to /dev/urandom,
-     * but the caller wants to know whether we have high quality numbers. Poll
-     * /dev/random to find out. */
-
-    if (seen_high_quality) {
-        /* We cache the positive result. Once kernel has entropy, we will get
-         * good random numbers. */
-        return 1;
-    }
-
-    fd = open("/dev/random", O_RDONLY | O_CLOEXEC | O_NOCTTY);
-    if (fd < 0)
-        return -errno;
-
-    r = nm_utils_fd_wait_for_event(fd, POLLIN, block ? -1 : 0);
-
-    if (r <= 0) {
-        nm_assert(r < 0 || !block);
-        return r;
-    }
-
-    nm_assert(r == 1);
-    seen_high_quality = TRUE;
-    return 1;
-}
-
-/*****************************************************************************/
-
-typedef struct _nm_packed {
-    uintptr_t heap_ptr;
-    uintptr_t stack_ptr;
-    gint64    now_bootime;
-    gint64    now_real;
-    pid_t     pid;
-    pid_t     ppid;
-    pid_t     tid;
-    guint32   grand[16];
-    guint8    auxval[16];
-    guint8    getrandom_buf[20];
-} BadRandSeed;
-
-typedef struct _nm_packed {
-    guint64 counter;
-    union {
-        guint8 full[NM_UTILS_CHECKSUM_LENGTH_SHA256];
-        struct {
-            guint8 half_1[NM_UTILS_CHECKSUM_LENGTH_SHA256 / 2];
-            guint8 half_2[NM_UTILS_CHECKSUM_LENGTH_SHA256 / 2];
-        };
-    } sha_digest;
-    union {
-        guint8  u8[NM_UTILS_CHECKSUM_LENGTH_SHA256 / 2];
-        guint32 u32[((NM_UTILS_CHECKSUM_LENGTH_SHA256 / 2) + 3) / 4];
-    } rand_vals;
-    guint8 rand_vals_getrandom[16];
-    gint64 rand_vals_timestamp;
-} BadRandState;
-
 static void
-_bad_random_init_seed(BadRandSeed *seed)
+dev_random_wait(void)
 {
-    const guint8 *p_at_random;
-    int           seed_idx;
-    GRand        *rand;
-
-    /* g_rand_new() reads /dev/urandom too, but we already know that
-     * /dev/urandom fails to give us good randomness (which is why
-     * we hit the "bad random" code path). So this may not be as
-     * good as we wish, but let's hope that it it does something smart
-     * to give some extra entropy... */
-    rand = g_rand_new();
-
-    /* Get some seed material from a GRand. */
-    for (seed_idx = 0; seed_idx < (int) G_N_ELEMENTS(seed->grand); seed_idx++)
-        seed->grand[seed_idx] = g_rand_int(rand);
+    static bool   has_waited = false;
+    struct pollfd random_fd  = {.events = POLLIN};
+    int           ret;
 
-    /* Add an address from the heap and stack, maybe ASLR helps a bit? */
-    seed->heap_ptr  = (uintptr_t) ((gpointer) rand);
-    seed->stack_ptr = (uintptr_t) ((gpointer) &rand);
-
-    g_rand_free(rand);
+    if (has_waited)
+        return;
 
-    /* Add the per-process, random number. */
-    p_at_random = ((gpointer) getauxval(AT_RANDOM));
-    if (p_at_random) {
-        G_STATIC_ASSERT(sizeof(seed->auxval) == 16);
-        memcpy(&seed->auxval, p_at_random, 16);
+    random_fd.fd = open("/dev/random", O_RDONLY);
+    nm_assert(random_fd.fd >= 0);
+    for (;;) {
+        ret = poll(&random_fd, 1, -1);
+        if (ret == 1)
+            break;
+        nm_assert(ret == -1 && errno == EINTR);
     }
-
-    _getrandom_best_effort(seed->getrandom_buf, sizeof(seed->getrandom_buf));
-
-    seed->now_bootime = nm_utils_clock_gettime_nsec(CLOCK_BOOTTIME);
-    seed->now_real    = g_get_real_time();
-    seed->pid         = getpid();
-    seed->ppid        = getppid();
-    seed->tid         = nm_utils_gettid();
+    nm_close(random_fd.fd);
+    has_waited = true;
 }
 
-static void
-_bad_random_bytes(guint8 *buf, gsize n)
+static ssize_t
+dev_urandom_read_full(void *buf, size_t count)
 {
-    nm_auto_free_checksum GChecksum *sum = g_checksum_new(G_CHECKSUM_SHA256);
-
-    nm_assert(n > 0);
+    nm_auto_close int fd = open("/dev/urandom", O_RDONLY);
 
-    /* We are in the fallback code path, where getrandom() (and /dev/urandom) failed
-     * to give us good randomness. Try our best.
-     *
-     * Our ability to get entropy for the CPRNG is very limited and thus the overall
-     * result will be bad randomness.
-     *
-     * Once we have some seed material, we combine GRand (which is not a cryptographically
-     * secure PRNG) with some iterative sha256 hashing. It would be nice if we had
-     * easy access to chacha20, but it's probably more cumbersome to fork those
-     * implementations than hack a bad CPRNG by using sha256 hashing. After all, this
-     * is fallback code to get *some* bad randomness. And with the inability to get a good
-     * seed, any CPRNG can only give us bad randomness. */
-
-    {
-        static BadRandState gl_state;
-        static GRand       *gl_rand;
-        static GMutex       gl_mutex;
-        NM_G_MUTEX_LOCKED(&gl_mutex);
-
-        if (G_UNLIKELY(!gl_rand)) {
-            union {
-                BadRandSeed d_seed;
-                guint32     d_u32[(sizeof(BadRandSeed) + 3) / 4];
-            } data = {
-                .d_u32 = {0},
-            };
-
-            _bad_random_init_seed(&data.d_seed);
-
-            gl_rand = g_rand_new_with_seed_array(data.d_u32, G_N_ELEMENTS(data.d_u32));
-
-            g_checksum_update(sum, (const guchar *) &data, sizeof(data));
-            nm_utils_checksum_get_digest(sum, gl_state.sha_digest.full);
-        }
-
-        _getrandom_best_effort(gl_state.rand_vals_getrandom, sizeof(gl_state.rand_vals_getrandom));
-
-        gl_state.rand_vals_timestamp = nm_utils_clock_gettime_nsec(CLOCK_BOOTTIME);
-
-        while (TRUE) {
-            int i;
-
-            gl_state.counter++;
-            for (i = 0; i < G_N_ELEMENTS(gl_state.rand_vals.u32); i++)
-                gl_state.rand_vals.u32[i] = g_rand_int(gl_rand);
-            g_checksum_reset(sum);
-            g_checksum_update(sum, (const guchar *) &gl_state, sizeof(gl_state));
-            nm_utils_checksum_get_digest(sum, gl_state.sha_digest.full);
-
-            /* gl_state.sha_digest.full and gl_state.rand_vals contain now our
-             * bad random values, but they are also the state for the next iteration.
-             * We must not directly expose that state to the caller, so XOR the values.
-             *
-             * That means, per iteration we can generate 16 bytes of bad randomness. That
-             * is suitable to initialize a random UUID. */
-            for (i = 0; i < (int) (NM_UTILS_CHECKSUM_LENGTH_SHA256 / 2); i++) {
-                nm_assert(n > 0);
-                buf[0] = gl_state.sha_digest.half_1[i] ^ gl_state.sha_digest.half_2[i]
-                         ^ gl_state.rand_vals.u8[i];
-                buf++;
-                n--;
-                if (n == 0)
-                    return;
-            }
-        }
-    }
+    nm_assert(fd >= 0);
+    return nm_utils_fd_read_loop_exact(fd, buf, count, FALSE);
 }
 
-/*****************************************************************************/
-
 /**
- * nm_random_get_bytes_full:
+ * nm_random_get_bytes:
  * @p: the buffer to fill
- * @n: the number of bytes to write to @p.
- * @out_high_quality: (out) (optional): whether the returned
- *   random bytes are of high quality.
- *
- * - will never block
- * - will always produce some numbers, but they may not
- *   be of high quality.
- * - Whether they are of high quality, you can know via @out_high_quality.
- * - will always try hard to produce high quality numbers, and on success
- *   they are as good as nm_random_get_crypto_bytes().
+ * @n: the number of bytes to fill
  */
 void
-nm_random_get_bytes_full(void *p, size_t n, gboolean *out_high_quality)
+nm_random_get_bytes(void *p, size_t n)
 {
-    int      fd;
-    int      r;
-    gboolean has_high_quality;
-    ssize_t  l;
+    ssize_t ret;
 
-    if (n == 0) {
-        NM_SET_OUT(out_high_quality, TRUE);
+    ret = getrandom_full(p, n, 0);
+    if (ret == 0)
         return;
-    }
-
-    g_return_if_fail(p);
-
-again_getrandom:
-    l = _getrandom(p, n, GRND_NONBLOCK);
-    if (l > 0) {
-        if ((size_t) l == n) {
-            NM_SET_OUT(out_high_quality, TRUE);
-            return;
-        }
-        p = ((uint8_t *) p) + l;
-        n -= l;
-        goto again_getrandom;
-    }
-
-    /* getrandom() failed. Fallback to read /dev/urandom. */
-
-    if (l == -ENOSYS) {
-        /* no support for getrandom(). */
-        if (out_high_quality) {
-            /* The caller wants to know whether we have high quality. Poll /dev/random
-             * to find out. */
-            has_high_quality = (_random_check_entropy(FALSE) > 0);
-        } else {
-            /* The value doesn't matter in this case. It will be unused. */
-            has_high_quality = FALSE;
-        }
-    } else {
-        /* Any other failure of getrandom() means we don't have high quality. */
-        has_high_quality = FALSE;
-        if (l == -EAGAIN) {
-            /* getrandom(GRND_NONBLOCK) failed because lack of entropy. Retry with GRND_INSECURE. */
-            for (;;) {
-                l = _getrandom_insecure(p, n);
-                if (l > 0) {
-                    if ((size_t) l == n) {
-                        NM_SET_OUT(out_high_quality, FALSE);
-                        return;
-                    }
-                    p = ((uint8_t *) p) + l;
-                    n -= l;
-                    continue;
-                }
-                /* Any error. Fallback to /dev/urandom. */
-                break;
-            }
-        }
-    }
-
-again_open:
-    fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC | O_NOCTTY);
-    if (fd < 0) {
-        if (errno == EINTR)
-            goto again_open;
-    } else {
-        r = nm_utils_fd_read_loop_exact(fd, p, n, TRUE);
-        nm_close(fd);
-        if (r >= 0) {
-            NM_SET_OUT(out_high_quality, has_high_quality);
-            return;
-        }
-    }
-
-    /* we failed to fill the bytes reading from /dev/urandom.
-     * Fill the bits using our fallback approach (which obviously
-     * cannot give high quality random).
-     */
-    _bad_random_bytes(p, n);
-    NM_SET_OUT(out_high_quality, FALSE);
-}
-
-/*****************************************************************************/
-
-/**
- * nm_random_get_crypto_bytes:
- * @p: the buffer to fill
- * @n: the number of bytes to fill
- *
- * - can fail (in which case a negative number is returned
- *   and the output buffer is undefined).
- * - will block trying to get high quality random numbers.
- */
-int
-nm_random_get_crypto_bytes(void *p, size_t n)
-{
-    nm_auto_close int fd = -1;
-    ssize_t           l;
-    int               r;
-
-    if (n == 0)
-        return 0;
-
-    nm_assert(p);
-
-again_getrandom:
-    l = _getrandom(p, n, 0);
-    if (l > 0) {
-        if ((size_t) l == n)
-            return 0;
-        p = (uint8_t *) p + l;
-        n -= l;
-        goto again_getrandom;
-    }
-
-    if (l != -ENOSYS) {
-        /* We got a failure, but getrandom seems to be working in principle. We
-         * won't get good numbers. Fail. */
-        return l;
-    }
-
-    /* getrandom() failed with ENOSYS. Fallback to reading /dev/urandom. */
-
-    r = _random_check_entropy(TRUE);
-    if (r < 0)
-        return r;
-    if (r == 0)
-        return nm_assert_unreachable_val(-EIO);
-
-    fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC | O_NOCTTY);
-    if (fd < 0)
-        return -errno;
+    nm_assert(ret == 0 || (ret == -1 && errno == ENOSYS));
 
-    return nm_utils_fd_read_loop_exact(fd, p, n, FALSE);
+    dev_random_wait();
+    ret = dev_urandom_read_full(p, n);
+    nm_assert(ret == 0);
 }
 
 /*****************************************************************************/
 
 guint64
-nm_random_u64_range_full(guint64 begin, guint64 end, gboolean crypto_bytes)
+nm_random_u64_range(guint64 begin, guint64 end)
 {
-    gboolean bad_crypto_bytes = FALSE;
-    guint64  remainder;
-    guint64  maxvalue;
-    guint64  x;
-    guint64  m;
+    guint64 remainder;
+    guint64 maxvalue;
+    guint64 x;
+    guint64 m;
 
-    /* Returns a random #guint64 equally distributed in the range [@begin..@end-1].
-     *
-     * The function always set errno. It either sets it to zero or to EAGAIN
-     * (if crypto_bytes were requested but not obtained). In any case, the function
-     * will always return a random number in the requested range (worst case, it's
-     * not crypto_bytes despite being requested). Check errno if you care. */
+    /* Returns a random #guint64 equally distributed in the range [@begin..@end-1]. */
 
     if (begin >= end) {
         /* systemd's random_u64_range(0) is an alias for nm_random_u64().
@@ -483,19 +149,9 @@ nm_random_u64_range_full(guint64 begin, guint64 end, gboolean crypto_bytes)
     maxvalue  = G_MAXUINT64 - remainder;
 
     do
-        if (crypto_bytes) {
-            if (nm_random_get_crypto_bytes(&x, sizeof(x)) < 0) {
-                /* Cannot get good crypto numbers. We will try our best, but fail
-                 * and set errno below. */
-                crypto_bytes     = FALSE;
-                bad_crypto_bytes = TRUE;
-                continue;
-            }
-        } else
-            nm_random_get_bytes(&x, sizeof(x));
+        nm_random_get_bytes(&x, sizeof(x));
     while (x >= maxvalue);
 
 out:
-    errno = bad_crypto_bytes ? EAGAIN : 0;
     return begin + (x % m);
 }
diff --git a/src/libnm-glib-aux/nm-random-utils.h b/src/libnm-glib-aux/nm-random-utils.h
index 729d71a4..43501940 100644
--- a/src/libnm-glib-aux/nm-random-utils.h
+++ b/src/libnm-glib-aux/nm-random-utils.h
@@ -6,15 +6,7 @@
 #ifndef __NM_RANDOM_UTILS_H__
 #define __NM_RANDOM_UTILS_H__
 
-void nm_random_get_bytes_full(void *p, size_t n, gboolean *out_high_quality);
-
-static inline void
-nm_random_get_bytes(void *p, size_t n)
-{
-    nm_random_get_bytes_full(p, n, NULL);
-}
-
-int nm_random_get_crypto_bytes(void *p, size_t n);
+void nm_random_get_bytes(void *p, size_t n);
 
 static inline guint32
 nm_random_u32(void)
@@ -43,12 +35,6 @@ nm_random_bool(void)
     return ch % 2u;
 }
 
-guint64 nm_random_u64_range_full(guint64 begin, guint64 end, gboolean crypto_bytes);
-
-static inline guint64
-nm_random_u64_range(guint64 end)
-{
-    return nm_random_u64_range_full(0, end, FALSE);
-}
+guint64 nm_random_u64_range(guint64 begin, guint64 end);
 
 #endif /* __NM_RANDOM_UTILS_H__ */
diff --git a/src/libnm-glib-aux/nm-secret-utils.h b/src/libnm-glib-aux/nm-secret-utils.h
index c175bc8f..dfbaa9a9 100644
--- a/src/libnm-glib-aux/nm-secret-utils.h
+++ b/src/libnm-glib-aux/nm-secret-utils.h
@@ -97,19 +97,19 @@ nm_secret_ptr_clear(NMSecretPtr *secret)
 #define nm_auto_clear_secret_ptr nm_auto(nm_secret_ptr_clear)
 
 #define NM_SECRET_PTR_INIT() \
-    ((const NMSecretPtr){    \
+    ((const NMSecretPtr) {   \
         .len = 0,            \
         .ptr = NULL,         \
     })
 
-#define NM_SECRET_PTR_STATIC(_len) \
-    ((const NMSecretPtr){          \
-        .len = _len,               \
-        .ptr = ((guint8[_len]){}), \
+#define NM_SECRET_PTR_STATIC(_len)  \
+    ((const NMSecretPtr) {          \
+        .len = _len,                \
+        .ptr = ((guint8[_len]) {}), \
     })
 
 #define NM_SECRET_PTR_ARRAY(_arr)                      \
-    ((const NMSecretPtr){                              \
+    ((const NMSecretPtr) {                             \
         .len = G_N_ELEMENTS(_arr) * sizeof((_arr)[0]), \
         .ptr = &((_arr)[0]),                           \
     })
diff --git a/src/libnm-glib-aux/nm-shared-utils.c b/src/libnm-glib-aux/nm-shared-utils.c
index 25c78fd3..db730b28 100644
--- a/src/libnm-glib-aux/nm-shared-utils.c
+++ b/src/libnm-glib-aux/nm-shared-utils.c
@@ -32,8 +32,8 @@ G_STATIC_ASSERT(G_STRUCT_OFFSET(NMUtilsNamedValue, value_ptr) == sizeof(const ch
 
 /*****************************************************************************/
 
-const char _nm_hexchar_table_lower[16] = "0123456789abcdef";
-const char _nm_hexchar_table_upper[16] = "0123456789ABCDEF";
+const char _nm_hexchar_table_lower[] = "0123456789abcdef";
+const char _nm_hexchar_table_upper[] = "0123456789ABCDEF";
 
 const void *const _NM_PTRARRAY_EMPTY[1] = {NULL};
 
@@ -1535,7 +1535,7 @@ _char_lookup_table_set_all(CharLookupTable *lookup, const char *candidates)
 static void
 _char_lookup_table_init(CharLookupTable *lookup, const char *candidates)
 {
-    *lookup = (CharLookupTable){
+    *lookup = (CharLookupTable) {
         .table = {0},
     };
     if (candidates)
@@ -3025,6 +3025,60 @@ nm_utils_buf_utf8safe_escape_cp(gconstpointer buf, gssize buflen, NMUtilsStrUtf8
     return s ?: g_strdup(s_const);
 }
 
+/**
+ * nm_utils_buf_utf8safe_escape_strv:
+ * @strv: an array of strings of length @strv_len
+ * @strv_len: the length of @strv, or -1 for a NULL terminated strv array.
+ * @flags: #NMUtilsStrUtf8SafeFlags flags
+ * @to_free: (out): return the pointer location of the newly created
+ *   strv if copying was necessary.
+ *
+ * Ensures all strings in a strv are valid UTF-8, copying them unless they
+ * need to be escaped, and escaping them using nm_utils_buf_utf8safe_escape().
+ *
+ * Returns: a strv with all its strings escaped, as valid UTF-8. All the strings
+ *   contained within are escaped using nm_utils_buf_utf8safe_escape().
+ *   If no escaping was necessary it returns the input @strv.
+ *   Otherwise, an allocated strv @to_free is returned which must be freed
+ *   by the caller with g_strfreev().
+ **/
+const char *const *
+nm_utils_buf_utf8safe_escape_strv(const char *const      *strv,
+                                  gssize                  strv_len,
+                                  NMUtilsStrUtf8SafeFlags flags,
+                                  char                 ***out_to_free)
+{
+    char **new_strv = NULL;
+    guint  len;
+
+    g_return_val_if_fail(strv, NULL);
+    g_return_val_if_fail(out_to_free, NULL);
+
+    *out_to_free = NULL;
+    len          = strv_len < 0 ? g_strv_length((char **) strv) : strv_len;
+
+    for (guint i = 0; i < len; ++i) {
+        char *to_free_str = NULL;
+
+        nm_utils_buf_utf8safe_escape(strv[i], -1, flags, &to_free_str);
+
+        if (to_free_str) {
+            if (!new_strv) {
+                new_strv = nm_strv_dup(strv, len, TRUE);
+            }
+
+            g_free(new_strv[i]);
+            new_strv[i] = to_free_str;
+        }
+    }
+
+    if (new_strv) {
+        return (const char *const *) (*out_to_free = new_strv);
+    }
+
+    return strv;
+}
+
 /*****************************************************************************/
 
 const char *
@@ -3677,7 +3731,7 @@ nm_utils_hashtable_cmp(const GHashTable *a,
     g_hash_table_iter_init(&h, hash_a);
     while (g_hash_table_iter_next(&h, &i_key, &i_val)) {
         nm_assert(i < size);
-        cmp_array_a[i++] = (HashTableCmpData){
+        cmp_array_a[i++] = (HashTableCmpData) {
             .key = i_key,
             .val = i_val,
         };
@@ -3688,7 +3742,7 @@ nm_utils_hashtable_cmp(const GHashTable *a,
     g_hash_table_iter_init(&h, hash_b);
     while (g_hash_table_iter_next(&h, &i_key, &i_val)) {
         nm_assert(i < size);
-        cmp_array_b[i++] = (HashTableCmpData){
+        cmp_array_b[i++] = (HashTableCmpData) {
             .key = i_key,
             .val = i_val,
         };
@@ -3699,7 +3753,7 @@ nm_utils_hashtable_cmp(const GHashTable *a,
                       size,
                       sizeof(HashTableCmpData),
                       _hashtable_cmp_func,
-                      &((HashTableUserData){
+                      &((HashTableUserData) {
                           .cmp_keys  = cmp_keys,
                           .user_data = user_data,
                       }));
@@ -3708,7 +3762,7 @@ nm_utils_hashtable_cmp(const GHashTable *a,
                       size,
                       sizeof(HashTableCmpData),
                       _hashtable_cmp_func,
-                      &((HashTableUserData){
+                      &((HashTableUserData) {
                           .cmp_keys  = cmp_keys,
                           .user_data = user_data,
                       }));
@@ -4456,7 +4510,7 @@ _nm_utils_invoke_on_idle_start(gboolean                    use_timeout,
     g_return_if_fail(callback);
 
     data  = g_slice_new(InvokeOnIdleData);
-    *data = (InvokeOnIdleData){
+    *data = (InvokeOnIdleData) {
         .callback           = callback,
         .callback_user_data = callback_user_data,
         .cancellable        = nm_g_object_ref(cancellable),
@@ -5244,7 +5298,7 @@ _ctx_integ_source_prepare(GSource *source, int *out_timeout)
 
             if (G_UNLIKELY(!poll_data)) {
                 poll_data  = g_slice_new(PollData);
-                *poll_data = (PollData){
+                *poll_data = (PollData) {
                     .fd                = fd->fd,
                     .idx.one           = i,
                     .has_many_idx      = FALSE,
@@ -7262,7 +7316,7 @@ nm_utils_poll(int                               poll_timeout_ms,
     PollTaskData *poll_task_data;
 
     poll_task_data  = g_slice_new(PollTaskData);
-    *poll_task_data = (PollTaskData){
+    *poll_task_data = (PollTaskData) {
         .task             = nm_g_task_new(NULL, cancellable, nm_utils_poll, callback, user_data),
         .probe_start_fcn  = probe_start_fcn,
         .probe_finish_fcn = probe_finish_fcn,
diff --git a/src/libnm-glib-aux/nm-shared-utils.h b/src/libnm-glib-aux/nm-shared-utils.h
index 70f1912e..4fa538e2 100644
--- a/src/libnm-glib-aux/nm-shared-utils.h
+++ b/src/libnm-glib-aux/nm-shared-utils.h
@@ -137,6 +137,7 @@ typedef enum {
     NM_LINK_TYPE_IP6GRE,
     NM_LINK_TYPE_IP6GRETAP,
     NM_LINK_TYPE_IPIP,
+    NM_LINK_TYPE_IPVLAN,
     NM_LINK_TYPE_LOOPBACK,
     NM_LINK_TYPE_MACSEC,
     NM_LINK_TYPE_MACVLAN,
@@ -279,12 +280,7 @@ typedef struct _NMUtilsIPv6IfaceId {
     };
 } NMUtilsIPv6IfaceId;
 
-#define NM_UTILS_IPV6_IFACE_ID_INIT \
-    {                               \
-        {                           \
-            .id = 0                 \
-        }                           \
-    }
+#define NM_UTILS_IPV6_IFACE_ID_INIT {{.id = 0}}
 
 /**
  * nm_utils_ipv6_addr_set_interface_identifier:
@@ -1299,6 +1295,12 @@ const char *nm_utils_buf_utf8safe_escape(gconstpointer           buf,
                                          char                  **to_free);
 char *
 nm_utils_buf_utf8safe_escape_cp(gconstpointer buf, gssize buflen, NMUtilsStrUtf8SafeFlags flags);
+
+const char *const *nm_utils_buf_utf8safe_escape_strv(const char *const      *strv,
+                                                     gssize                  strv_len,
+                                                     NMUtilsStrUtf8SafeFlags flags,
+                                                     char                 ***out_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,
@@ -2422,28 +2424,28 @@ int     nm_utils_fd_read_loop_exact(int fd, void *buf, size_t nbytes, bool do_po
 /*****************************************************************************/
 
 #define NM_DEFINE_GDBUS_ARG_INFO_FULL(name_, ...) \
-    ((GDBusArgInfo *) (&((const GDBusArgInfo){.ref_count = -1, .name = name_, __VA_ARGS__})))
+    ((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_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__})))
+        (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_PROPERTY_INFOS(...)                  \
+    ((GDBusPropertyInfo **) ((const GDBusPropertyInfo *[]) { \
+        __VA_ARGS__ NULL,                                    \
     }))
 
 #define NM_DEFINE_GDBUS_SIGNAL_INFO_INIT(name_, ...) {.ref_count = -1, .name = name_, __VA_ARGS__}
@@ -2452,9 +2454,9 @@ int     nm_utils_fd_read_loop_exact(int fd, void *buf, size_t nbytes, bool do_po
     ((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_SIGNAL_INFOS(...)                \
+    ((GDBusSignalInfo **) ((const GDBusSignalInfo *[]) { \
+        __VA_ARGS__ NULL,                                \
     }))
 
 #define NM_DEFINE_GDBUS_METHOD_INFO_INIT(name_, ...) {.ref_count = -1, .name = name_, __VA_ARGS__}
@@ -2463,9 +2465,9 @@ int     nm_utils_fd_read_loop_exact(int fd, void *buf, size_t nbytes, bool do_po
     ((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_METHOD_INFOS(...)                \
+    ((GDBusMethodInfo **) ((const GDBusMethodInfo *[]) { \
+        __VA_ARGS__ NULL,                                \
     }))
 
 #define NM_DEFINE_GDBUS_INTERFACE_INFO_INIT(name_, ...) \
@@ -2476,7 +2478,7 @@ int     nm_utils_fd_read_loop_exact(int fd, void *buf, size_t nbytes, bool do_po
         (const GDBusInterfaceInfo) NM_DEFINE_GDBUS_INTERFACE_INFO_INIT(name_, __VA_ARGS__))))
 
 #define NM_DEFINE_GDBUS_INTERFACE_VTABLE(...) \
-    ((GDBusInterfaceVTable *) (&((const GDBusInterfaceVTable){__VA_ARGS__})))
+    ((GDBusInterfaceVTable *) (&((const GDBusInterfaceVTable) {__VA_ARGS__})))
 
 /*****************************************************************************/
 
@@ -2498,7 +2500,7 @@ typedef struct _NMUtilsUserData NMUtilsUserData;
 NMUtilsUserData *_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__})
+    _nm_utils_user_data_pack(NM_NARG(__VA_ARGS__), (gconstpointer[]) {__VA_ARGS__})
 
 void _nm_utils_user_data_unpack(NMUtilsUserData *user_data, int nargs, ...);
 
@@ -2638,8 +2640,8 @@ int nm_utils_getpagesize(void);
 
 /*****************************************************************************/
 
-extern const char _nm_hexchar_table_lower[16];
-extern const char _nm_hexchar_table_upper[16];
+extern const char _nm_hexchar_table_lower[];
+extern const char _nm_hexchar_table_upper[];
 
 static inline char
 nm_hexchar(int x, gboolean upper_case)
diff --git a/src/libnm-glib-aux/nm-test-utils.h b/src/libnm-glib-aux/nm-test-utils.h
index 2a6a5d3a..feb86301 100644
--- a/src/libnm-glib-aux/nm-test-utils.h
+++ b/src/libnm-glib-aux/nm-test-utils.h
@@ -1002,7 +1002,7 @@ _nmtst_add_test_func_full(const char      *testpath,
     data = g_malloc(G_STRUCT_OFFSET(NmtstTestData, args)
                     + (sizeof(gpointer) * (n_args + 1u) + testpath_len));
 
-    *data = (NmtstTestData){
+    *data = (NmtstTestData) {
         .testpath       = (gpointer) &data->args[n_args + 1u],
         ._func_test     = func_test,
         ._func_setup    = func_setup,
diff --git a/src/libnm-glib-aux/nm-uuid.h b/src/libnm-glib-aux/nm-uuid.h
index b8955452..3613902f 100644
--- a/src/libnm-glib-aux/nm-uuid.h
+++ b/src/libnm-glib-aux/nm-uuid.h
@@ -7,13 +7,13 @@ typedef struct _NMUuid {
     guint8 uuid[16];
 } NMUuid;
 
-#define NM_UUID_INIT_ZERO() ((NMUuid){.uuid = {0}})
+#define NM_UUID_INIT_ZERO() ((NMUuid) {.uuid = {0}})
 
 /* Beware, the 16 macro arguments are two hex-digits, not plain numbers. The macro
  * will automatically add the "0x". In particular, "09" is not an octal number, it's
  * 0x09. This oddity is so that the arguments look very much like the UUID in string form. */
 #define NM_UUID_INIT(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) \
-    ((NMUuid){                                                                             \
+    ((NMUuid) {                                                                            \
         .uuid = {(0x##a0),                                                                 \
                  (0x##a1),                                                                 \
                  (0x##a2),                                                                 \
diff --git a/src/libnm-glib-aux/nm-value-type.h b/src/libnm-glib-aux/nm-value-type.h
index 771021da..6a0379b7 100644
--- a/src/libnm-glib-aux/nm-value-type.h
+++ b/src/libnm-glib-aux/nm-value-type.h
@@ -60,7 +60,7 @@ typedef union {
     ({                                            \
         NMValueTypUnion *const _arg2 = (_arg);    \
                                                   \
-        *_arg2 = (NMValueTypUnion){               \
+        *_arg2 = (NMValueTypUnion) {              \
             ._type = (_val),                      \
         };                                        \
         _arg2;                                    \
@@ -75,7 +75,7 @@ typedef struct {
     ({                                                 \
         NMValueTypUnioMaybe *const _arg2 = (_arg);     \
                                                        \
-        *_arg2 = (NMValueTypUnioMaybe){                \
+        *_arg2 = (NMValueTypUnioMaybe) {               \
             .has       = TRUE,                         \
             .val._type = (_val),                       \
         };                                             \
diff --git a/src/libnm-glib-aux/tests/test-json-aux.c b/src/libnm-glib-aux/tests/test-json-aux.c
index 32462a29..b0ca1e6d 100644
--- a/src/libnm-glib-aux/tests/test-json-aux.c
+++ b/src/libnm-glib-aux/tests/test-json-aux.c
@@ -88,16 +88,16 @@ test_jansson(void)
     CHECK_FCN(vt,
               json_array_get,
               nm_json_t * (*_f_nm)(const nm_json_t *, gsize),
-              json_t * (*_f_js)(const json_t *, size_t));
+              json_t * (*_f_js)(const json_t *, size_t) );
     CHECK_FCN(vt,
               json_array_size,
               gsize(*_f_nm)(const nm_json_t *),
-              size_t(*_f_js)(const json_t *));
+              size_t (*_f_js)(const json_t *));
     CHECK_FCN(vt, json_delete, void (*_f_nm)(nm_json_t *), void (*_f_js)(json_t *));
     CHECK_FCN(vt,
               json_dumps,
               char *(*_f_nm)(const nm_json_t *, gsize),
-              char *(*_f_js)(const json_t *, size_t));
+              char *(*_f_js)(const json_t *, size_t) );
     CHECK_FCN(vt, json_false, nm_json_t * (*_f_nm)(void), json_t * (*_f_js)(void) );
     CHECK_FCN(vt, json_integer, nm_json_t * (*_f_nm)(nm_json_int_t), json_t * (*_f_js)(json_int_t));
     CHECK_FCN(vt,
@@ -138,7 +138,7 @@ test_jansson(void)
     CHECK_FCN(vt,
               json_object_size,
               gsize(*_f_nm)(const nm_json_t *),
-              size_t(*_f_js)(const json_t *));
+              size_t (*_f_js)(const json_t *));
     CHECK_FCN(vt,
               json_string,
               nm_json_t * (*_f_nm)(const char *),
diff --git a/src/libnm-glib-aux/tests/test-shared-general.c b/src/libnm-glib-aux/tests/test-shared-general.c
index b19ac1ce..2f09a549 100644
--- a/src/libnm-glib-aux/tests/test-shared-general.c
+++ b/src/libnm-glib-aux/tests/test-shared-general.c
@@ -197,10 +197,7 @@ test_nm_random(void)
         if (begin >= end)
             continue;
 
-        if (begin == 0 && nmtst_get_rand_bool())
-            x = nm_random_u64_range(end);
-        else
-            x = nm_random_u64_range_full(begin, end, nmtst_get_rand_bool());
+        x = nm_random_u64_range(begin, end);
 
         g_assert_cmpuint(x, >=, begin);
         g_assert_cmpuint(x, <, end);
@@ -1622,17 +1619,17 @@ test_parse_env_file(void)
     gs_free char      *arg2 = NULL;
     int                r;
 
-#define env_file_1                  \
-    "a=a\n"                         \
-    "a=b\n"                         \
-    "a=b\n"                         \
-    "a=a\n"                         \
-    "b=b\\\n"                       \
-    "c\n"                           \
-    "d= d\\\n"                      \
-    "e  \\\n"                       \
-    "f  \n"                         \
-    "g=g\\ \n"                      \
+#define env_file_1        \
+    "a=a\n"               \
+    "a=b\n"               \
+    "a=b\n"               \
+    "a=a\n"               \
+    "b=b\\\n"             \
+    "c\n"                 \
+    "d= d\\\n"            \
+    "e  \\\n"             \
+    "f  \n"               \
+    "g=g\\ \n"            \
     "h= ąęół\\ śćńźżµ \n" \
     "i=i\\"
     r = nm_parse_env_file_full(env_file_1, _env_file_push_cb, &data);