summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2014-12-22 17:59:16 +0100
committerThomas Haller <thaller@redhat.com>2015-01-11 13:08:34 +0100
commit41e6c4fac1890e4302e4bfd1aa21be362cce51f2 (patch)
tree9a9515997755876d3d9e75a93ff984ce9f07441c
parent2cb3c7e8a0164219dcbdc06a4fe073527bb23b7b (diff)
downloadNetworkManager-41e6c4fac1890e4302e4bfd1aa21be362cce51f2.tar.gz
platform: workaround deletion of IPv4 route with metric 0
Deleting routes with metric 0 might end up deleting other routes with a different metric. Workaround this in platform to only delete a route with metric 0 if such a route can be found prior to deletion. Don't only look into the cache (which might be out of date). Instead refetch the route we are about to delete to be sure. There is still a race that we might end up deleting the wrong route. https://bugzilla.gnome.org/show_bug.cgi?id=741871 https://bugzilla.redhat.com/show_bug.cgi?id=1172780
-rw-r--r--src/platform/nm-linux-platform.c13
1 files changed, 13 insertions, 0 deletions
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
index d59b55bc1f..0c35376cdb 100644
--- a/src/platform/nm-linux-platform.c
+++ b/src/platform/nm-linux-platform.c
@@ -3912,6 +3912,19 @@ ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, int plen
cache = choose_cache_by_type (platform, OBJECT_TYPE_IP4_ROUTE);
+ if (metric == 0) {
+ /* Deleting an IPv4 route with metric 0 does not only delete an exectly matching route.
+ * If no route with metric 0 exists, it might delete another route to the same destination.
+ * For nm_platform_ip4_route_delete() we don't want this semantic.
+ *
+ * Instead, re-fetch the route from kernel, and if that fails, there is nothing to do.
+ * On success, there is still a race that we might end up deleting the wrong route. */
+ if (!refresh_object (platform, (struct nl_object *) route, FALSE, NM_PLATFORM_REASON_INTERNAL)) {
+ rtnl_route_put ((struct rtnl_route *) route);
+ return TRUE;
+ }
+ }
+
/* when deleting an IPv4 route, several fields of the provided route must match.
* Lookup in the cache so that we hopefully get the right values. */
cached_object = (struct rtnl_route *) nl_cache_search (cache, route);