From a041e431dac5ddcdb5946634082cb626f3c67340 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 19 Jul 2017 13:03:28 +0200 Subject: [PATCH] platform: use correct scope for deleting IPv4 route Refactor _nl_msg_new_route() to obtain the route scope (rtm_scope) from the NMPObject, instead of a separate argument. That way, when deleting an IPv4 route, we don't pick the first route that matches (RT_SCOPE_NOWHERE), but use the actual scope of the route that we want to delete. That matters, if there are more then one otherwise identical routes that only differ by their scope. For kernel, the scope of IPv6 routes is always global (RT_SCOPE_UNIVERSE). Also, during ip4_route_add() initialize the intermediate @obj to have the values as we expect them after adding the route. That is necessary to use it in _nl_msg_new_route(). But also nicer for consistency. Also, move the scope_inv field in NMPlatformIP4Route to let the other in_addr_t fields life side by side. --- src/platform/nm-linux-platform.c | 10 +++++----- src/platform/nm-platform.c | 2 ++ src/platform/nm-platform.h | 17 +++++++++++++---- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index 795e4680cd..2a743401b6 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -2419,7 +2419,6 @@ static struct nl_msg * _nl_msg_new_route (int nlmsg_type, int nlmsg_flags, const NMPObject *obj, - unsigned char scope, gconstpointer gateway, guint32 mss, gconstpointer pref_src, @@ -2440,7 +2439,9 @@ _nl_msg_new_route (int nlmsg_type, .rtm_tos = obj->ip_route.tos, .rtm_table = RT_TABLE_MAIN, /* omit setting RTA_TABLE attribute */ .rtm_protocol = nmp_utils_ip_config_source_coerce_to_rtprot (obj->ip_route.rt_source), - .rtm_scope = scope, + .rtm_scope = is_v4 + ? nm_platform_route_scope_inv (obj->ip4_route.scope_inv) + : RT_SCOPE_NOWHERE, .rtm_type = RTN_UNICAST, .rtm_flags = 0, .rtm_dst_len = obj->ip_route.plen, @@ -5695,11 +5696,12 @@ ip4_route_add (NMPlatform *platform, const NMPlatformIP4Route *route) r = NMP_OBJECT_CAST_IP4_ROUTE (&obj); r->network = nm_utils_ip4_address_clear_host_address (r->network, r->plen); r->rt_source = nmp_utils_ip_config_source_round_trip_rtprot (r->rt_source), + r->scope_inv = nm_platform_route_scope_inv (!r->gateway + ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE); nlmsg = _nl_msg_new_route (RTM_NEWROUTE, NLM_F_CREATE | NLM_F_REPLACE, &obj, - route->gateway ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK, &route->gateway, route->mss, route->pref_src ? &route->pref_src : NULL, @@ -5729,7 +5731,6 @@ ip6_route_add (NMPlatform *platform, const NMPlatformIP6Route *route) nlmsg = _nl_msg_new_route (RTM_NEWROUTE, NLM_F_CREATE | NLM_F_REPLACE, &obj, - IN6_IS_ADDR_UNSPECIFIED (&route->gateway) ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE, &route->gateway, route->mss, !IN6_IS_ADDR_UNSPECIFIED (&route->pref_src) ? &route->pref_src : NULL, @@ -5791,7 +5792,6 @@ ip_route_delete (NMPlatform *platform, nlmsg = _nl_msg_new_route (RTM_DELROUTE, 0, obj, - RT_SCOPE_NOWHERE, NULL, 0, NULL, diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index b8443ccf1f..c8b3e160c1 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -4752,6 +4752,7 @@ nm_platform_ip4_route_hash (const NMPlatformIP4Route *obj, NMPlatformIPRouteCmpT if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID) { h = NM_HASH_COMBINE (h, obj->ifindex); h = NM_HASH_COMBINE (h, obj->rt_source); + h = NM_HASH_COMBINE (h, obj->scope_inv); } break; case NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY: @@ -4805,6 +4806,7 @@ nm_platform_ip4_route_cmp (const NMPlatformIP4Route *a, const NMPlatformIP4Route if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID) { NM_CMP_FIELD (a, b, ifindex); NM_CMP_FIELD (a, b, rt_source); + NM_CMP_FIELD (a, b, scope_inv); } break; case NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY: diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h index 7f14626d8f..326abcdf21 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -379,13 +379,22 @@ struct _NMPlatformIP4Route { in_addr_t network; in_addr_t gateway; - /* The bitwise inverse of the route scope. It is inverted so that the - * default value (RT_SCOPE_NOWHERE) is nul. */ - guint8 scope_inv; - /* RTA_PREFSRC/rtnl_route_get_pref_src(). A value of zero means that * no pref-src is set. */ in_addr_t pref_src; + + /* The bitwise inverse of the route scope rtm_scope. It is inverted so that the + * default value (RT_SCOPE_NOWHERE) is zero. Use nm_platform_route_scope_inv() + * to convert back and forth between the inverese representation and the + * real value. + * + * rtm_scope is part of the primary key for IPv4 routes. When deleting a route, + * the scope must match, unless it is left at RT_SCOPE_NOWHERE, in which case the first + * matching route is deleted. + * + * For IPv6 routes, the scope is ignored and kernel always assumes global scope. + * Hence, this field is only in NMPlatformIP4Route. */ + guint8 scope_inv; }; struct _NMPlatformIP6Route {