summaryrefslogtreecommitdiff
path: root/src/nm-ip6-config.c
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2017-09-22 12:37:12 +0200
committerThomas Haller <thaller@redhat.com>2017-09-26 19:36:51 +0200
commit7cd04ce014732a5c50389dc0c6d9804a9e2c0e5c (patch)
treee34efcbda2e8624957cfceea6118d8db9ff18179 /src/nm-ip6-config.c
parent0fce60c767e60446220e492a259473ea29b78c7e (diff)
downloadNetworkManager-7cd04ce014732a5c50389dc0c6d9804a9e2c0e5c.tar.gz
core: inject route list to delete for nm_platform_ip_route_sync()
Whenever we call a platform operation that reads or writes the netlink socket, there is the possibility that the cache gets updated, as we receive netlink events. It is thus racy, if nm_platform_ip_route_sync() *first* adds routes, and then obtains a list of routes to delete. The correct approach is to determine which routes to delete first (and keep it in a list @routes_prune), and pass that list down to nm_platform_ip_route_sync(). Arguably, this doesn't yet solve every race. For example, NMDevice calls update_ext_ip_config() during ip4_config_merge_and_apply(). That is good, as it resyncs with platform. However, before calling nm_ip4_config_commit() it calls other platform operations, like _commit_mtu(). So, the race is still there.
Diffstat (limited to 'src/nm-ip6-config.c')
-rw-r--r--src/nm-ip6-config.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c
index fce5fa8e90..1c0094d94c 100644
--- a/src/nm-ip6-config.c
+++ b/src/nm-ip6-config.c
@@ -608,6 +608,7 @@ nm_ip6_config_commit (const NMIP6Config *self,
{
gs_unref_ptrarray GPtrArray *addresses = NULL;
gs_unref_ptrarray GPtrArray *routes = NULL;
+ gs_unref_ptrarray GPtrArray *routes_prune = NULL;
int ifindex;
gboolean success = TRUE;
@@ -618,16 +619,21 @@ nm_ip6_config_commit (const NMIP6Config *self,
addresses = nm_dedup_multi_objs_to_ptr_array_head (nm_ip6_config_lookup_addresses (self),
NULL, NULL);
+
routes = nm_dedup_multi_objs_to_ptr_array_head (nm_ip6_config_lookup_routes (self),
NULL, NULL);
+
+ routes_prune = nm_platform_ip_route_get_prune_list (platform,
+ AF_INET6,
+ ifindex);
+
nm_platform_ip6_address_sync (platform, ifindex, addresses, TRUE);
if (!nm_platform_ip_route_sync (platform,
AF_INET6,
ifindex,
routes,
- nm_platform_lookup_predicate_routes_main,
- NULL,
+ routes_prune,
out_temporary_not_available))
success = FALSE;