diff options
author | Thomas Haller <thaller@redhat.com> | 2017-09-22 12:37:12 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2017-09-26 19:36:51 +0200 |
commit | 7cd04ce014732a5c50389dc0c6d9804a9e2c0e5c (patch) | |
tree | e34efcbda2e8624957cfceea6118d8db9ff18179 /src/nm-ip6-config.c | |
parent | 0fce60c767e60446220e492a259473ea29b78c7e (diff) | |
download | NetworkManager-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.c | 10 |
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; |