platform: improve workaround for deleting IPv4 route with libnl guessing route scope

Previously, we always lookup the cache for libnl objects and used those for
delete_object(). This was necessary, because libnl guesses and overwrites
the IPv4 route scope.

Newer libnl no longer overwrites the scope if set explicitly to RT_SCOPE_NOWHERE.
So, this workaround is no longer needed. Indeed there might be cases, where it is
harmful, because we might guess the wrong scope.

This was fixed in libnl3 in commits
  85ec9c7ad8
  015c4ee59b

https://bugzilla.gnome.org/show_bug.cgi?id=726273

Signed-off-by: Thomas Haller <thaller@redhat.com>
This commit is contained in:
Thomas Haller
2014-02-23 14:57:50 +01:00
parent ff801bcafc
commit 019bf7512d

View File

@@ -1494,17 +1494,13 @@ delete_object (NMPlatform *platform, struct nl_object *obj)
{ {
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
auto_nl_object struct nl_object *obj_cleanup = obj; auto_nl_object struct nl_object *obj_cleanup = obj;
auto_nl_object struct nl_object *cached_object = NULL; struct nl_object *object = obj;
struct nl_object *object;
int object_type; int object_type;
int nle; int nle;
object_type = object_type_from_nl_object (obj); object_type = object_type_from_nl_object (obj);
g_return_val_if_fail (object_type != OBJECT_TYPE_UNKNOWN, FALSE); g_return_val_if_fail (object_type != OBJECT_TYPE_UNKNOWN, FALSE);
cached_object = nm_nl_cache_search (choose_cache_by_type (platform, object_type), obj);
object = cached_object ? cached_object : obj;
switch (object_type) { switch (object_type) {
case OBJECT_TYPE_LINK: case OBJECT_TYPE_LINK:
nle = rtnl_link_delete (priv->nlh, (struct rtnl_link *) object); nle = rtnl_link_delete (priv->nlh, (struct rtnl_link *) object);
@@ -3327,25 +3323,40 @@ ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, int plen
{ {
in_addr_t gateway = 0; in_addr_t gateway = 0;
struct nl_object *route = build_rtnl_route (AF_INET, ifindex, &network, plen, &gateway, metric, 0); struct nl_object *route = build_rtnl_route (AF_INET, ifindex, &network, plen, &gateway, metric, 0);
uint8_t scope = RT_SCOPE_NOWHERE;
g_return_val_if_fail (route, FALSE); g_return_val_if_fail (route, FALSE);
if (!_nl_has_capability (1 /* NL_CAPABILITY_ROUTE_BUILD_MSG_SET_SCOPE */)) {
/* When searching for a matching IPv4 route to delete, the kernel /* When searching for a matching IPv4 route to delete, the kernel
* searches for a matching scope, unless the RTM_DELROUTE message * searches for a matching scope, unless the RTM_DELROUTE message
* specifies RT_SCOPE_NOWHERE (see fib_table_delete()). * specifies RT_SCOPE_NOWHERE (see fib_table_delete()).
* *
* However, if we set the scope of @rtnlroute to RT_SCOPE_NOWHERE (or * However, if we set the scope of @rtnlroute to RT_SCOPE_NOWHERE (or
* leave it unset), rtnl_route_build_msg() will reset the scope to * leave it unset), rtnl_route_build_msg() will reset the scope to
* rtnl_route_guess_scope() -- which might be the wrong scope. * rtnl_route_guess_scope() -- which probably guesses wrong.
* *
* As a workaround, we set the scope to RT_SCOPE_UNIVERSE, so libnl * As a workaround, we look at the cached route and use that scope.
* will not overwrite it. But this only works if we guess correctly.
* *
* As a better workaround, we don't use @rtnlroute as argument for * Newer versions of libnl, no longer reset the scope if explicitly set to RT_SCOPE_NOWHERE.
* rtnl_route_delete(), but we look into our cache, if we already have * So, this workaround is only needed unless we have NL_CAPABILITY_ROUTE_BUILD_MSG_SET_SCOPE.
* this route ready.
**/ **/
rtnl_route_set_scope ((struct rtnl_route *) route, RT_SCOPE_UNIVERSE); struct nl_object *cached_object;
cached_object = nm_nl_cache_search (choose_cache_by_type (platform, OBJECT_TYPE_IP4_ROUTE), route);
if (cached_object) {
scope = rtnl_route_get_scope ((struct rtnl_route *) cached_object);
nl_object_put (cached_object);
}
if (scope == RT_SCOPE_NOWHERE) {
/* If we would set the scope to RT_SCOPE_NOWHERE, libnl would guess the scope.
* But probably it will guess 'link' because we don't set the next hop
* of the route we are about to delete. A better guess is 'global'. */
scope = RT_SCOPE_UNIVERSE;
}
}
rtnl_route_set_scope ((struct rtnl_route *) route, scope);
return delete_object (platform, route); return delete_object (platform, route);
} }