platform: properly consider address lifetimes in nm_platform_ip4_address_sync()

When checking whether an address from platform should be deleted, we
compare the address with our list of @known_addresses.
For that we must also check for expired lifetimes, because
@known_addresses might contain expired addresses.
This commit is contained in:
Thomas Haller 2015-06-24 12:00:22 +02:00
parent 347555795f
commit 8336bd2a83

View file

@ -39,6 +39,8 @@
#include "nm-enum-types.h"
#include "nm-core-internal.h"
#define ADDRESS_LIFETIME_PADDING 5
G_STATIC_ASSERT (sizeof ( ((NMPlatformLink *) NULL)->addr.data ) == NM_UTILS_HWADDR_LEN_MAX);
#define debug(...) nm_log_dbg (LOGD_PLATFORM, __VA_ARGS__)
@ -1954,7 +1956,7 @@ nm_platform_ip6_address_exists (NMPlatform *self, int ifindex, struct in6_addr a
}
static gboolean
array_contains_ip4_address (const GArray *addresses, const NMPlatformIP4Address *address)
array_contains_ip4_address (const GArray *addresses, const NMPlatformIP4Address *address, gint64 now, guint32 padding)
{
guint len = addresses ? addresses->len : 0;
guint i;
@ -1962,15 +1964,20 @@ array_contains_ip4_address (const GArray *addresses, const NMPlatformIP4Address
for (i = 0; i < len; i++) {
NMPlatformIP4Address *candidate = &g_array_index (addresses, NMPlatformIP4Address, i);
if (candidate->address == address->address && candidate->plen == address->plen)
return TRUE;
if (candidate->address == address->address && candidate->plen == address->plen) {
guint32 lifetime, preferred;
if (nmp_utils_lifetime_get (candidate->timestamp, candidate->lifetime, candidate->preferred,
now, padding, &lifetime, &preferred))
return TRUE;
}
}
return FALSE;
}
static gboolean
array_contains_ip6_address (const GArray *addresses, const NMPlatformIP6Address *address)
array_contains_ip6_address (const GArray *addresses, const NMPlatformIP6Address *address, gint64 now, guint32 padding)
{
guint len = addresses ? addresses->len : 0;
guint i;
@ -1978,8 +1985,13 @@ array_contains_ip6_address (const GArray *addresses, const NMPlatformIP6Address
for (i = 0; i < len; i++) {
NMPlatformIP6Address *candidate = &g_array_index (addresses, NMPlatformIP6Address, i);
if (IN6_ARE_ADDR_EQUAL (&candidate->address, &address->address) && candidate->plen == address->plen)
return TRUE;
if (IN6_ARE_ADDR_EQUAL (&candidate->address, &address->address) && candidate->plen == address->plen) {
guint32 lifetime, preferred;
if (nmp_utils_lifetime_get (candidate->timestamp, candidate->lifetime, candidate->preferred,
now, padding, &lifetime, &preferred))
return TRUE;
}
}
return FALSE;
@ -2033,7 +2045,7 @@ nm_platform_ip4_address_sync (NMPlatform *self, int ifindex, const GArray *known
for (i = 0; i < addresses->len; i++) {
address = &g_array_index (addresses, NMPlatformIP4Address, i);
if (!array_contains_ip4_address (known_addresses, address))
if (!array_contains_ip4_address (known_addresses, address, now, ADDRESS_LIFETIME_PADDING))
nm_platform_ip4_address_delete (self, ifindex, address->address, address->plen, address->peer_address);
}
g_array_free (addresses, TRUE);
@ -2048,9 +2060,8 @@ nm_platform_ip4_address_sync (NMPlatform *self, int ifindex, const GArray *known
guint32 network;
gboolean reinstall_device_route = FALSE;
/* add a padding of 5 seconds to avoid potential races. */
if (!nmp_utils_lifetime_get (known_address->timestamp, known_address->lifetime, known_address->preferred,
now, 5, &lifetime, &preferred))
now, ADDRESS_LIFETIME_PADDING, &lifetime, &preferred))
continue;
if (nm_platform_ip4_check_reinstall_device_route (self, ifindex, known_address, device_route_metric))
@ -2109,7 +2120,7 @@ nm_platform_ip6_address_sync (NMPlatform *self, int ifindex, const GArray *known
if (keep_link_local && IN6_IS_ADDR_LINKLOCAL (&address->address))
continue;
if (!array_contains_ip6_address (known_addresses, address))
if (!array_contains_ip6_address (known_addresses, address, now, ADDRESS_LIFETIME_PADDING))
nm_platform_ip6_address_delete (self, ifindex, address->address, address->plen);
}
g_array_free (addresses, TRUE);
@ -2122,9 +2133,8 @@ nm_platform_ip6_address_sync (NMPlatform *self, int ifindex, const GArray *known
const NMPlatformIP6Address *known_address = &g_array_index (known_addresses, NMPlatformIP6Address, i);
guint32 lifetime, preferred;
/* add a padding of 5 seconds to avoid potential races. */
if (!nmp_utils_lifetime_get (known_address->timestamp, known_address->lifetime, known_address->preferred,
now, 5, &lifetime, &preferred))
now, ADDRESS_LIFETIME_PADDING, &lifetime, &preferred))
continue;
if (!nm_platform_ip6_address_add (self, ifindex, known_address->address,