diff options
| author | Michael Biebl <biebl@debian.org> | 2022-05-13 15:11:15 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2022-05-13 15:11:15 +0200 |
| commit | 87d61411bb3453587d21487da04fcf770fee7d55 (patch) | |
| tree | e84f1bcc59ec448f8d6f8754391974f0f9bd6cd9 /src/libnm-platform | |
| parent | 9959fdb2e8ddd06f2161798ca0a39c77d67c652d (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.c | 91 | ||||
| -rw-r--r-- | src/libnm-platform/nm-platform.h | 42 |
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); |