summary refs log tree commit diff
path: root/src/libnm-glib-aux
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2025-08-01 19:15:13 +0200
committerMichael Biebl <biebl@debian.org>2025-08-01 19:15:13 +0200
commit7e9091a5960f67a84787c03153324915220e4816 (patch)
treedc743de962532932ebc3b4ed3a36ddd093d97d68 /src/libnm-glib-aux
parent582eb4472a0f3375042afb9026cbeb50e058a27d (diff)
New upstream version 1.54.0 upstream/1.54.0
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.c2
-rw-r--r--src/libnm-glib-aux/nm-dedup-multi.h2
-rw-r--r--src/libnm-glib-aux/nm-hash-utils.c21
-rw-r--r--src/libnm-glib-aux/nm-hash-utils.h13
-rw-r--r--src/libnm-glib-aux/nm-inet-utils.c36
-rw-r--r--src/libnm-glib-aux/nm-inet-utils.h2
-rw-r--r--src/libnm-glib-aux/nm-macros-internal.h17
-rw-r--r--src/libnm-glib-aux/nm-shared-utils.c22
-rw-r--r--src/libnm-glib-aux/nm-shared-utils.h3
-rw-r--r--src/libnm-glib-aux/nm-test-utils.h2
-rw-r--r--src/libnm-glib-aux/tests/test-shared-general.c48
12 files changed, 155 insertions, 15 deletions
diff --git a/src/libnm-glib-aux/nm-dbus-aux.c b/src/libnm-glib-aux/nm-dbus-aux.c
index 1be4047e..27bcf651 100644
--- a/src/libnm-glib-aux/nm-dbus-aux.c
+++ b/src/libnm-glib-aux/nm-dbus-aux.c
@@ -459,7 +459,7 @@ _bus_get_cb(GObject *source, GAsyncResult *result, gpointer user_data)
  *
  * This calls g_bus_get(), but iterates the current (thread-default) GMainContext
  * until the response is ready. As such, it's similar to g_bus_get_sync(),
- * but it allows to cancel the operation (without having multiple threads).
+ * but it allows one to cancel the operation (without having multiple threads).
  *
  * Returns: (transfer full): the new #GDBusConnection or %NULL on error.
  */
diff --git a/src/libnm-glib-aux/nm-dedup-multi.c b/src/libnm-glib-aux/nm-dedup-multi.c
index c80b17ce..973a7d13 100644
--- a/src/libnm-glib-aux/nm-dedup-multi.c
+++ b/src/libnm-glib-aux/nm-dedup-multi.c
@@ -149,7 +149,7 @@ _entry_unpack(const NMDedupMultiEntry    *entry,
     nm_assert(NM_IN_SET(*out_lookup_head, FALSE, TRUE));
     ASSERT_idx_type(*out_idx_type);
 
-    /* for lookup of the head, we allow to omit object, but only
+    /* for lookup of the head, we allow one to omit object, but only
      * if the idx_type does not partition the objects. Otherwise, we
      * require a obj to compare. */
     nm_assert(!*out_lookup_head || (*out_obj || !(*out_idx_type)->klass->idx_obj_partition_equal));
diff --git a/src/libnm-glib-aux/nm-dedup-multi.h b/src/libnm-glib-aux/nm-dedup-multi.h
index ebc5d0a1..b548b2a5 100644
--- a/src/libnm-glib-aux/nm-dedup-multi.h
+++ b/src/libnm-glib-aux/nm-dedup-multi.h
@@ -221,7 +221,7 @@ struct _NMDedupMultiHeadEntry {
 static inline gconstpointer
 nm_dedup_multi_entry_get_obj(const NMDedupMultiEntry *entry)
 {
-    /* convenience method that allows to skip the %NULL check on
+    /* convenience method that allows one to skip the %NULL check on
      * @entry. Think of the NULL-conditional operator ?. of C# */
     return entry ? entry->obj : NULL;
 }
diff --git a/src/libnm-glib-aux/nm-hash-utils.c b/src/libnm-glib-aux/nm-hash-utils.c
index 973422a1..7f25e9ac 100644
--- a/src/libnm-glib-aux/nm-hash-utils.c
+++ b/src/libnm-glib-aux/nm-hash-utils.c
@@ -190,6 +190,27 @@ nm_pint_equal(gconstpointer a, gconstpointer b)
     return s1 == s2 || (s1 && s2 && *s1 == *s2);
 }
 
+/* GHashFunc for GHashTable keys that are a pointer to a guint64 */
+guint
+nm_puint64_hash(gconstpointer p)
+{
+    const guint64 *s = p;
+
+    if (!s)
+        return nm_hash_static(298377461u);
+    return nm_hash_val(1208815757u, *s);
+}
+
+/* GEqualFunc for GHashTable keys that are a pointer to a guint64 */
+gboolean
+nm_puint64_equal(gconstpointer a, gconstpointer b)
+{
+    const guint64 *s1 = a;
+    const guint64 *s2 = a;
+
+    return s1 == s2 || (s1 && s2 && *s1 == *s2);
+}
+
 guint
 nm_pdirect_hash(gconstpointer p)
 {
diff --git a/src/libnm-glib-aux/nm-hash-utils.h b/src/libnm-glib-aux/nm-hash-utils.h
index 6d7cc271..9fbcbdb3 100644
--- a/src/libnm-glib-aux/nm-hash-utils.h
+++ b/src/libnm-glib-aux/nm-hash-utils.h
@@ -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
@@ -224,7 +224,7 @@ guint nm_hash_ptr(gconstpointer ptr);
 #define nm_direct_hash nm_hash_ptr
 
 guint nm_hash_str(const char *str);
-#define nm_str_hash ((guint(*)(gconstpointer str)) nm_hash_str)
+#define nm_str_hash ((guint (*)(gconstpointer str)) nm_hash_str)
 
 #define nm_hash_vals(static_seed, ...)         \
     ({                                         \
@@ -266,6 +266,9 @@ gboolean nm_pstr_equal(gconstpointer a, gconstpointer b);
 guint    nm_pint_hash(gconstpointer p);
 gboolean nm_pint_equal(gconstpointer a, gconstpointer b);
 
+guint    nm_puint64_hash(gconstpointer p);
+gboolean nm_puint64_equal(gconstpointer a, gconstpointer b);
+
 G_STATIC_ASSERT(sizeof(int) == sizeof(guint32));
 #define nm_puint32_hash  nm_pint_hash
 #define nm_puint32_equal nm_pint_equal
diff --git a/src/libnm-glib-aux/nm-inet-utils.c b/src/libnm-glib-aux/nm-inet-utils.c
index 2ee73ad5..f4f418cf 100644
--- a/src/libnm-glib-aux/nm-inet-utils.c
+++ b/src/libnm-glib-aux/nm-inet-utils.c
@@ -238,6 +238,42 @@ nm_ip6_addr_clear_host_address(struct in6_addr *dst, const struct in6_addr *src,
     return dst;
 }
 
+/**
+ * nm_ip6_addr_get_subnet_id:
+ * @addr: the IPv6 address
+ * @plen: the prefix length
+ *
+ * Given an IPv6 address and a prefix length, returns the subnet ID,
+ * defined as follows:
+ *
+ * |     plen bits   | (64 - plen) bits |          64 bits              |
+ * +-----------------+------------------+-------------------------------+
+ * |      prefix     |    subnet ID     |        interface ID           |
+ * +-----------------+------------------+-------------------------------+
+ *
+ * The prefix length must be a value between 0 and 64.
+ */
+guint64
+nm_ip6_addr_get_subnet_id(struct in6_addr *addr, guint8 plen)
+{
+    int     nbits = 64 - plen;
+    guint64 res   = 0;
+    guint64 tmp;
+    guint64 i;
+
+    g_return_val_if_fail(addr, 0);
+    g_return_val_if_fail(plen <= 64, 0);
+
+    for (i = 0; i < 2 && nbits > 0; i++, nbits -= 32) {
+        tmp = htonl(addr->s6_addr32[1 - i]);
+        tmp = tmp & ((1ULL << NM_MIN(32U, (guint) nbits)) - 1);
+        tmp = tmp << (32 * i);
+        res += tmp;
+    }
+
+    return res;
+}
+
 int
 nm_ip6_addr_same_prefix_cmp(const struct in6_addr *addr_a,
                             const struct in6_addr *addr_b,
diff --git a/src/libnm-glib-aux/nm-inet-utils.h b/src/libnm-glib-aux/nm-inet-utils.h
index 489d21dd..999519f8 100644
--- a/src/libnm-glib-aux/nm-inet-utils.h
+++ b/src/libnm-glib-aux/nm-inet-utils.h
@@ -218,6 +218,8 @@ nm_ip4_addr_clear_host_address(in_addr_t addr, guint32 plen)
 const struct in6_addr *
 nm_ip6_addr_clear_host_address(struct in6_addr *dst, const struct in6_addr *src, guint32 plen);
 
+guint64 nm_ip6_addr_get_subnet_id(struct in6_addr *addr, guint8 plen);
+
 /*****************************************************************************/
 
 static inline int
diff --git a/src/libnm-glib-aux/nm-macros-internal.h b/src/libnm-glib-aux/nm-macros-internal.h
index 151e7a4f..940e8c30 100644
--- a/src/libnm-glib-aux/nm-macros-internal.h
+++ b/src/libnm-glib-aux/nm-macros-internal.h
@@ -1021,6 +1021,22 @@ nm_g_variant_equal(GVariant *a, GVariant *b)
 
 /*****************************************************************************/
 
+#if defined(__GNUC__) && (__GNUC__ >= 12)
+#define _NM_BACKPORT_SYMBOL_IMPL(version,                                                        \
+                                 return_type,                                                    \
+                                 orig_func,                                                      \
+                                 versioned_func,                                                 \
+                                 args_typed,                                                     \
+                                 args)                                                           \
+    return_type versioned_func args_typed;                                                       \
+                                                                                                 \
+    __attribute__((__symver__(                                                                   \
+        G_STRINGIFY(orig_func) "@" G_STRINGIFY(version)))) return_type versioned_func args_typed \
+    {                                                                                            \
+        return orig_func args;                                                                   \
+    }                                                                                            \
+    return_type orig_func args_typed;
+#else
 #define _NM_BACKPORT_SYMBOL_IMPL(version,                                                       \
                                  return_type,                                                   \
                                  orig_func,                                                     \
@@ -1035,6 +1051,7 @@ nm_g_variant_equal(GVariant *a, GVariant *b)
     return_type orig_func args_typed;                                                           \
     __asm__(".symver " G_STRINGIFY(versioned_func) ", " G_STRINGIFY(orig_func) "@" G_STRINGIFY( \
         version))
+#endif
 
 #define NM_BACKPORT_SYMBOL(version, return_type, func, args_typed, args) \
     _NM_BACKPORT_SYMBOL_IMPL(version, return_type, func, _##func##_##version, args_typed, args)
diff --git a/src/libnm-glib-aux/nm-shared-utils.c b/src/libnm-glib-aux/nm-shared-utils.c
index db730b28..e39831c6 100644
--- a/src/libnm-glib-aux/nm-shared-utils.c
+++ b/src/libnm-glib-aux/nm-shared-utils.c
@@ -2898,7 +2898,7 @@ nm_utils_buf_utf8safe_unescape(const char             *str,
  *
  * Depending on @flags, valid UTF-8 characters are not escaped at all
  * (except the escape character '\\'). This is the difference to g_strescape(),
- * which escapes all non-ASCII characters. This allows to pass on
+ * which escapes all non-ASCII characters. This allows one to pass on
  * valid UTF-8 characters as-is and can be directly shown to the user
  * as UTF-8 -- with exception of the backslash escape character,
  * invalid UTF-8 sequences, and other (depending on @flags).
@@ -3113,7 +3113,7 @@ nm_utils_str_utf8safe_unescape(const char *str, NMUtilsStrUtf8SafeFlags flags, c
  *
  * Depending on @flags, valid UTF-8 characters are not escaped at all
  * (except the escape character '\\'). This is the difference to g_strescape(),
- * which escapes all non-ASCII characters. This allows to pass on
+ * which escapes all non-ASCII characters. This allows one to pass on
  * valid UTF-8 characters as-is and can be directly shown to the user
  * as UTF-8 -- with exception of the backslash escape character,
  * invalid UTF-8 sequences, and other (depending on @flags).
@@ -6004,8 +6004,8 @@ nm_utils_is_localhost(const char *name)
     return FALSE;
 }
 
-gboolean
-nm_utils_is_specific_hostname(const char *name)
+static gboolean
+_nm_utils_check_hostname(const char *name, bool allow_localhost)
 {
     if (nm_str_is_empty(name))
         return FALSE;
@@ -6016,7 +6016,7 @@ nm_utils_is_specific_hostname(const char *name)
         return FALSE;
     }
 
-    if (nm_utils_is_localhost(name))
+    if (!allow_localhost && nm_utils_is_localhost(name))
         return FALSE;
 
     /* FIXME: properly validate the hostname, like systemd's hostname_is_valid() */
@@ -6024,6 +6024,18 @@ nm_utils_is_specific_hostname(const char *name)
     return TRUE;
 }
 
+gboolean
+nm_utils_is_specific_hostname(const char *name)
+{
+    return _nm_utils_check_hostname(name, FALSE);
+}
+
+gboolean
+nm_utils_is_not_empty_hostname(const char *name)
+{
+    return _nm_utils_check_hostname(name, TRUE);
+}
+
 /*****************************************************************************/
 
 typedef struct {
diff --git a/src/libnm-glib-aux/nm-shared-utils.h b/src/libnm-glib-aux/nm-shared-utils.h
index 4fa538e2..1fca6015 100644
--- a/src/libnm-glib-aux/nm-shared-utils.h
+++ b/src/libnm-glib-aux/nm-shared-utils.h
@@ -2143,7 +2143,7 @@ nm_g_ptr_array_pdata(const GPtrArray *arr)
  *   must agree with the owner-ship semantics of @func.
  *
  * This is a replacement for g_ptr_array_copy(), which is not available
- * before glib 2.62. Since GPtrArray does not allow to access the internal
+ * before glib 2.62. Since GPtrArray does not allow one to access the internal
  * element_free_func, we cannot add a compatibility implementation of g_ptr_array_copy()
  * as the caller must provide the correct element_free_func.
  *
@@ -3419,6 +3419,7 @@ char *_nm_utils_format_variant_attributes(GHashTable                          *a
 gboolean nm_utils_is_localhost(const char *name);
 
 gboolean nm_utils_is_specific_hostname(const char *name);
+gboolean nm_utils_is_not_empty_hostname(const char *name);
 
 struct passwd;
 
diff --git a/src/libnm-glib-aux/nm-test-utils.h b/src/libnm-glib-aux/nm-test-utils.h
index feb86301..98b3f3d0 100644
--- a/src/libnm-glib-aux/nm-test-utils.h
+++ b/src/libnm-glib-aux/nm-test-utils.h
@@ -1504,7 +1504,7 @@ _nmtst_main_loop_quit_on_notify(GObject *object, GParamSpec *pspec, gpointer use
                                                    (timeout_msec),                                \
                                                    (poll_msec),                                   \
                                                    condition))                                    \
-            g_assert(FALSE &&#condition);                                                         \
+            g_assert(FALSE && #condition);                                                        \
     }                                                                                             \
     G_STMT_END
 
diff --git a/src/libnm-glib-aux/tests/test-shared-general.c b/src/libnm-glib-aux/tests/test-shared-general.c
index 2f09a549..931c25c6 100644
--- a/src/libnm-glib-aux/tests/test-shared-general.c
+++ b/src/libnm-glib-aux/tests/test-shared-general.c
@@ -398,6 +398,53 @@ test_nm_ip4_addr_netmask_from_prefix(void)
 /*****************************************************************************/
 
 static void
+test_nm_ip6_addr_get_subnet_id(void)
+{
+#define check_subnet_id(_addrstr, _plen, _subnet_id)                              \
+    {                                                                             \
+        struct in6_addr addr;                                                     \
+                                                                                  \
+        addr = nmtst_inet6_from_string(_addrstr);                                 \
+        g_assert_cmpint(nm_ip6_addr_get_subnet_id(&addr, _plen), ==, _subnet_id); \
+    }
+
+    check_subnet_id("aaaa:bbbb:cccc:ffff::", 64, 0);
+    check_subnet_id("aaaa:bbbb:cccc:fffe::", 63, 0);
+    check_subnet_id("aaaa:bbbb:cccc:ffff::", 63, 1);
+    check_subnet_id("aaaa:bbbb:cccc:fffc::", 62, 0);
+    check_subnet_id("aaaa:bbbb:cccc:fffd::", 62, 1);
+    check_subnet_id("aaaa:bbbb:cccc:fffe::", 62, 2);
+    check_subnet_id("aaaa:bbbb:cccc:ffff::", 62, 3);
+    check_subnet_id("aaaa:bbbb:cccc:fff8::", 61, 0);
+    check_subnet_id("aaaa:bbbb:cccc:ffff::", 61, 7);
+    check_subnet_id("aaaa:bbbb:cccc:fff0::", 60, 0);
+    check_subnet_id("aaaa:bbbb:cccc:fff2::", 60, 2);
+    check_subnet_id("aaaa:bbbb:cccc:ffff::", 60, 15);
+    check_subnet_id("aaaa:bbbb:cccc:0000::", 48, 0);
+    check_subnet_id("aaaa:bbbb:cccc:f000::", 48, 61440);
+    check_subnet_id("aaaa:bbbb:cccc:ffff::", 48, 65535);
+    check_subnet_id("aaaa:bbbb:cccc:0000::", 46, 0);
+    check_subnet_id("aaaa:bbbb:cccc:0001::", 46, 1);
+    check_subnet_id("aaaa:bbbb:ccce:5555::", 46, 152917);
+    check_subnet_id("aaaa:bbbb:0000:0000::", 32, 0);
+    check_subnet_id("aaaa:bbbb:0000:0001::", 32, 1);
+    check_subnet_id("aaaa:bbbb:0001:0001::", 32, 65537);
+    check_subnet_id("aaaa:bbbb:ffff:ffff::", 32, 0xffffffff);
+    check_subnet_id("aaaa:bbb8:0000:0000::", 30, 0);
+    check_subnet_id("aaaa:bbb8:0000:0001::", 30, 1);
+    check_subnet_id("aaaa:bbb8:0001:0001::", 30, 65537);
+    check_subnet_id("aaaa:bbbb:0000:0000::", 30, 0x300000000ULL);
+    check_subnet_id("aaaa:bbbb:0001:0001::", 30, 0x300010001ULL);
+    check_subnet_id("aaaa:bbbb:0001:0001::", 8, 0xAABBBB00010001ULL);
+    check_subnet_id("abaa:bbbb:0001:0001::", 7, 0x1AABBBB00010001ULL);
+    check_subnet_id("abaa:bbbb:0001:0001::", 0, 0xABAABBBB00010001ULL);
+    check_subnet_id("abaa:bbbb:0001:0001:5555:5555:5555:5555", 0, 0xABAABBBB00010001ULL);
+    check_subnet_id("::", 0, 0);
+}
+
+/*****************************************************************************/
+
+static void
 test_unaligned(void)
 {
     int shift;
@@ -2864,6 +2911,7 @@ main(int argc, char **argv)
     g_test_add_func("/general/test_nm_ip4_addr_is_loopback", test_nm_ip4_addr_is_loopback);
     g_test_add_func("/general/test_nm_ip4_addr_netmask_from_prefix",
                     test_nm_ip4_addr_netmask_from_prefix);
+    g_test_add_func("/general/test_nm_ip6_addr_get_subnet_id", test_nm_ip6_addr_get_subnet_id);
     g_test_add_func("/general/test_unaligned", test_unaligned);
     g_test_add_func("/general/test_strv_cmp", test_strv_cmp);
     g_test_add_func("/general/test_strstrip_avoid_copy", test_strstrip_avoid_copy);