summary refs log tree commit diff
path: root/src/libnm-platform
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2022-05-13 15:11:15 +0200
committerMichael Biebl <biebl@debian.org>2022-05-13 15:11:15 +0200
commit87d61411bb3453587d21487da04fcf770fee7d55 (patch)
treee84f1bcc59ec448f8d6f8754391974f0f9bd6cd9 /src/libnm-platform
parent9959fdb2e8ddd06f2161798ca0a39c77d67c652d (diff)
New upstream version 1.38.0 upstream/1.38.0
Diffstat (limited to 'src/libnm-platform')
-rw-r--r--src/libnm-platform/nm-platform.c91
-rw-r--r--src/libnm-platform/nm-platform.h42
2 files changed, 79 insertions, 54 deletions
diff --git a/src/libnm-platform/nm-platform.c b/src/libnm-platform/nm-platform.c
index 8866a436..090af26d 100644
--- a/src/libnm-platform/nm-platform.c
+++ b/src/libnm-platform/nm-platform.c
@@ -4459,15 +4459,25 @@ gboolean
 nm_platform_ip_address_flush(NMPlatform *self, int addr_family, int ifindex)
 {
     gboolean success = TRUE;
+    int      IS_IPv4;
 
     _CHECK_SELF(self, klass, FALSE);
 
-    nm_assert(NM_IN_SET(addr_family, AF_UNSPEC, AF_INET, AF_INET6));
+    nm_assert_addr_family_or_unspec(addr_family);
+
+    for (IS_IPv4 = 1; IS_IPv4 >= 0; IS_IPv4--) {
+        gs_unref_ptrarray GPtrArray *addresses_prune = NULL;
+        const int                    addr_family2    = IS_IPv4 ? AF_INET : AF_INET6;
+
+        if (!NM_IN_SET(addr_family, AF_UNSPEC, addr_family2))
+            continue;
 
-    if (NM_IN_SET(addr_family, AF_UNSPEC, AF_INET))
-        success &= nm_platform_ip4_address_sync(self, ifindex, NULL);
-    if (NM_IN_SET(addr_family, AF_UNSPEC, AF_INET6))
-        success &= nm_platform_ip6_address_sync(self, ifindex, NULL, TRUE);
+        addresses_prune =
+            nm_platform_ip_address_get_prune_list(self, addr_family2, ifindex, NULL, 0);
+
+        if (!nm_platform_ip_address_sync(self, addr_family2, ifindex, NULL, addresses_prune))
+            success = FALSE;
+    }
     return success;
 }
 
@@ -4509,17 +4519,31 @@ _err_inval_due_to_ipv6_tentative_pref_src(NMPlatform *self, const NMPObject *obj
     return TRUE;
 }
 
-GPtrArray *
-nm_platform_ip_address_get_prune_list(NMPlatform *self,
-                                      int         addr_family,
-                                      int         ifindex,
-                                      gboolean    exclude_ipv6_temporary_addrs)
+static guint
+_ipv6_temporary_addr_prefixes_keep_hash(gconstpointer ptr)
 {
-    const int                    IS_IPv4 = NM_IS_IPv4(addr_family);
-    const NMDedupMultiHeadEntry *head_entry;
-    NMPLookup                    lookup;
-    GPtrArray                   *result = NULL;
-    CList                       *iter;
+    return nm_hash_mem(1161670183u, ptr, 8);
+}
+
+static gboolean
+_ipv6_temporary_addr_prefixes_keep_equal(gconstpointer ptr_a, gconstpointer ptr_b)
+{
+    return !memcmp(ptr_a, ptr_b, 8);
+}
+
+GPtrArray *
+nm_platform_ip_address_get_prune_list(NMPlatform            *self,
+                                      int                    addr_family,
+                                      int                    ifindex,
+                                      const struct in6_addr *ipv6_temporary_addr_prefixes_keep,
+                                      guint                  ipv6_temporary_addr_prefixes_keep_len)
+{
+    gs_unref_hashtable GHashTable *ipv6_temporary_addr_prefixes_keep_idx = NULL;
+    const int                      IS_IPv4                               = NM_IS_IPv4(addr_family);
+    const NMDedupMultiHeadEntry   *head_entry;
+    NMPLookup                      lookup;
+    GPtrArray                     *result = NULL;
+    CList                         *iter;
 
     nmp_lookup_init_object(&lookup, NMP_OBJECT_TYPE_IP_ADDRESS(NM_IS_IPv4(addr_family)), ifindex);
 
@@ -4532,9 +4556,40 @@ nm_platform_ip_address_get_prune_list(NMPlatform *self,
         const NMPObject *obj = c_list_entry(iter, NMDedupMultiEntry, lst_entries)->obj;
 
         if (!IS_IPv4) {
-            if (exclude_ipv6_temporary_addrs
-                && NM_FLAGS_HAS(NMP_OBJECT_CAST_IP_ADDRESS(obj)->n_ifa_flags, IFA_F_SECONDARY))
-                continue;
+            const NMPlatformIP6Address *a6 = NMP_OBJECT_CAST_IP6_ADDRESS(obj);
+
+            if (NM_FLAGS_HAS(a6->n_ifa_flags, IFA_F_SECONDARY)
+                && ipv6_temporary_addr_prefixes_keep_len > 0 && a6->plen == 64) {
+                gboolean keep = FALSE;
+                guint    i;
+
+                if (ipv6_temporary_addr_prefixes_keep_len < 10) {
+                    for (i = 0; i < ipv6_temporary_addr_prefixes_keep_len; i++) {
+                        if (memcmp(&ipv6_temporary_addr_prefixes_keep[i], &a6->address, 8) == 0) {
+                            keep = TRUE;
+                            break;
+                        }
+                    }
+                } else {
+                    /* We have a larger number of addresses. We want that our functions are O(n),
+                     * so build a lookup index. */
+                    if (!ipv6_temporary_addr_prefixes_keep_idx) {
+                        ipv6_temporary_addr_prefixes_keep_idx =
+                            g_hash_table_new(_ipv6_temporary_addr_prefixes_keep_hash,
+                                             _ipv6_temporary_addr_prefixes_keep_equal);
+                        for (i = 0; i < ipv6_temporary_addr_prefixes_keep_len; i++) {
+                            g_hash_table_add(ipv6_temporary_addr_prefixes_keep_idx,
+                                             (gpointer) &ipv6_temporary_addr_prefixes_keep[i]);
+                        }
+                    }
+                    if (g_hash_table_contains(ipv6_temporary_addr_prefixes_keep_idx, &a6->address))
+                        keep = TRUE;
+                }
+                if (keep) {
+                    /* This IPv6 temporary address has a prefix that we want to keep. */
+                    continue;
+                }
+            }
         }
 
         if (!result)
diff --git a/src/libnm-platform/nm-platform.h b/src/libnm-platform/nm-platform.h
index 246d6ff6..5c72fade 100644
--- a/src/libnm-platform/nm-platform.h
+++ b/src/libnm-platform/nm-platform.h
@@ -2187,42 +2187,12 @@ gboolean nm_platform_ip_address_sync(NMPlatform *self,
                                      GPtrArray  *known_addresses,
                                      GPtrArray  *addresses_prune);
 
-GPtrArray *nm_platform_ip_address_get_prune_list(NMPlatform *self,
-                                                 int         addr_family,
-                                                 int         ifindex,
-                                                 gboolean    exclude_ipv6_temporary_addrs);
-
-static inline gboolean
-_nm_platform_ip_address_sync(NMPlatform *self,
-                             int         addr_family,
-                             int         ifindex,
-                             GPtrArray  *known_addresses,
-                             gboolean    full_sync)
-{
-    gs_unref_ptrarray GPtrArray *addresses_prune = NULL;
-
-    addresses_prune = nm_platform_ip_address_get_prune_list(self, addr_family, ifindex, !full_sync);
-    return nm_platform_ip_address_sync(self,
-                                       addr_family,
-                                       ifindex,
-                                       known_addresses,
-                                       addresses_prune);
-}
-
-static inline gboolean
-nm_platform_ip4_address_sync(NMPlatform *self, int ifindex, GPtrArray *known_addresses)
-{
-    return _nm_platform_ip_address_sync(self, AF_INET, ifindex, known_addresses, TRUE);
-}
-
-static inline gboolean
-nm_platform_ip6_address_sync(NMPlatform *self,
-                             int         ifindex,
-                             GPtrArray  *known_addresses,
-                             gboolean    full_sync)
-{
-    return _nm_platform_ip_address_sync(self, AF_INET6, ifindex, known_addresses, full_sync);
-}
+GPtrArray *
+nm_platform_ip_address_get_prune_list(NMPlatform            *self,
+                                      int                    addr_family,
+                                      int                    ifindex,
+                                      const struct in6_addr *ipv6_temporary_addr_prefixes_keep,
+                                      guint                  ipv6_temporary_addr_prefixes_keep_len);
 
 gboolean nm_platform_ip_address_flush(NMPlatform *self, int addr_family, int ifindex);