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 commits85ec9c7ad8
015c4ee59b
https://bugzilla.gnome.org/show_bug.cgi?id=726273 Signed-off-by: Thomas Haller <thaller@redhat.com>
This commit is contained in:
@@ -1494,17 +1494,13 @@ delete_object (NMPlatform *platform, struct nl_object *obj)
|
||||
{
|
||||
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
|
||||
auto_nl_object struct nl_object *obj_cleanup = obj;
|
||||
auto_nl_object struct nl_object *cached_object = NULL;
|
||||
struct nl_object *object;
|
||||
struct nl_object *object = obj;
|
||||
int object_type;
|
||||
int nle;
|
||||
|
||||
object_type = object_type_from_nl_object (obj);
|
||||
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) {
|
||||
case OBJECT_TYPE_LINK:
|
||||
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;
|
||||
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);
|
||||
|
||||
/* When searching for a matching IPv4 route to delete, the kernel
|
||||
* searches for a matching scope, unless the RTM_DELROUTE message
|
||||
* specifies RT_SCOPE_NOWHERE (see fib_table_delete()).
|
||||
*
|
||||
* 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
|
||||
* rtnl_route_guess_scope() -- which might be the wrong scope.
|
||||
*
|
||||
* As a workaround, we set the scope to RT_SCOPE_UNIVERSE, so libnl
|
||||
* will not overwrite it. But this only works if we guess correctly.
|
||||
*
|
||||
* As a better workaround, we don't use @rtnlroute as argument for
|
||||
* rtnl_route_delete(), but we look into our cache, if we already have
|
||||
* this route ready.
|
||||
**/
|
||||
rtnl_route_set_scope ((struct rtnl_route *) route, RT_SCOPE_UNIVERSE);
|
||||
if (!_nl_has_capability (1 /* NL_CAPABILITY_ROUTE_BUILD_MSG_SET_SCOPE */)) {
|
||||
/* When searching for a matching IPv4 route to delete, the kernel
|
||||
* searches for a matching scope, unless the RTM_DELROUTE message
|
||||
* specifies RT_SCOPE_NOWHERE (see fib_table_delete()).
|
||||
*
|
||||
* 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
|
||||
* rtnl_route_guess_scope() -- which probably guesses wrong.
|
||||
*
|
||||
* As a workaround, we look at the cached route and use that scope.
|
||||
*
|
||||
* Newer versions of libnl, no longer reset the scope if explicitly set to RT_SCOPE_NOWHERE.
|
||||
* So, this workaround is only needed unless we have NL_CAPABILITY_ROUTE_BUILD_MSG_SET_SCOPE.
|
||||
**/
|
||||
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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user