core: merge branch 'th/fix-clear-ip6-temp-addrs'
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1209
This commit is contained in:
@@ -4186,6 +4186,7 @@ _l3_commit_one(NML3Cfg *self,
|
||||
gboolean final_failure_for_temporary_not_available = FALSE;
|
||||
char sbuf_commit_type[50];
|
||||
gboolean success = TRUE;
|
||||
guint i;
|
||||
|
||||
nm_assert(NM_IS_L3CFG(self));
|
||||
nm_assert(NM_IN_SET(commit_type,
|
||||
@@ -4218,11 +4219,35 @@ _l3_commit_one(NML3Cfg *self,
|
||||
route_table_sync = NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN;
|
||||
|
||||
if (commit_type == NM_L3_CFG_COMMIT_TYPE_REAPPLY) {
|
||||
addresses_prune = nm_platform_ip_address_get_prune_list(self->priv.platform,
|
||||
addr_family,
|
||||
self->priv.ifindex,
|
||||
TRUE);
|
||||
routes_prune = nm_platform_ip_route_get_prune_list(self->priv.platform,
|
||||
gs_unref_array GArray *ipv6_temp_addrs_keep = NULL;
|
||||
|
||||
nm_platform_process_events(self->priv.platform);
|
||||
|
||||
if (!IS_IPv4 && addresses) {
|
||||
for (i = 0; i < addresses->len; i++) {
|
||||
const NMPlatformIP6Address *addr = NMP_OBJECT_CAST_IP6_ADDRESS(addresses->pdata[i]);
|
||||
|
||||
if (!NM_FLAGS_HAS(addr->n_ifa_flags, IFA_F_MANAGETEMPADDR))
|
||||
continue;
|
||||
|
||||
nm_assert(addr->plen == 64);
|
||||
|
||||
/* Construct a list of all IPv6 prefixes for which we (still) set
|
||||
* IFA_F_MANAGETEMPADDR (that is, for which we will have temporary addresses).
|
||||
* Those should not be pruned during reapply. */
|
||||
if (!ipv6_temp_addrs_keep)
|
||||
ipv6_temp_addrs_keep = g_array_new(FALSE, FALSE, sizeof(struct in6_addr));
|
||||
g_array_append_val(ipv6_temp_addrs_keep, addr->address);
|
||||
}
|
||||
}
|
||||
addresses_prune =
|
||||
nm_platform_ip_address_get_prune_list(self->priv.platform,
|
||||
addr_family,
|
||||
self->priv.ifindex,
|
||||
nm_g_array_data(ipv6_temp_addrs_keep),
|
||||
nm_g_array_len(ipv6_temp_addrs_keep));
|
||||
|
||||
routes_prune = nm_platform_ip_route_get_prune_list(self->priv.platform,
|
||||
addr_family,
|
||||
self->priv.ifindex,
|
||||
route_table_sync);
|
||||
|
@@ -2165,6 +2165,12 @@ char *nm_utils_g_slist_strlist_join(const GSList *a, const char *separator);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static inline gpointer
|
||||
nm_g_array_data(const GArray *arr)
|
||||
{
|
||||
return arr ? arr->data : NULL;
|
||||
}
|
||||
|
||||
static inline guint
|
||||
nm_g_array_len(const GArray *arr)
|
||||
{
|
||||
|
@@ -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);
|
||||
|
||||
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);
|
||||
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;
|
||||
|
||||
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)
|
||||
|
@@ -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);
|
||||
|
||||
|
Reference in New Issue
Block a user