diff options
author | Thomas Haller <thaller@redhat.com> | 2017-08-17 15:17:40 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2017-08-24 10:47:23 +0200 |
commit | 974ff6299633bf739a73a240797cd46ebcd0e043 (patch) | |
tree | 2805005423818cfe6e73b76fcc0c9e12c012ba46 /src | |
parent | 69a50a50531e2d8a8b6f679c25a13a5aedb5ea9e (diff) |
platform: fix handling rt_scope of IPv4 route
Kernel does not allow to add an IPv4 route with rt_scope RT_SCOPE_NOWHERE
(255). It would fail with EINVAL.
While adding a route, we coerce/normalize the scope in
nm_platform_ip_route_normalize(). However, that should only be
done, if the scope is not explicitly set already. Otherwise,
leave it unchanged.
nm_platform_ip_route_normalize() is related to the compare functions.
Several compare modes do a fuzzy comparison, and they should compare
equal as if they would be normalized. Hence, we must do the same
normalization there.
One pecularity in NetworkManager is that we track scope as it's
inverse. The reason is to have a default value of zero meaning
RT_SCOPE_NOWHERE. Hence "scope_inv".
Diffstat (limited to 'src')
-rw-r--r-- | src/platform/nm-platform.c | 43 |
1 files changed, 34 insertions, 9 deletions
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index f392537e2..e906ba3bc 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -3482,6 +3482,26 @@ nm_platform_ip_address_flush (NMPlatform *self, /*****************************************************************************/ +static guint8 +_ip_route_scope_inv_get_normalized (const NMPlatformIP4Route *route) +{ + /* in kernel, you cannot set scope to RT_SCOPE_NOWHERE (255). + * That means, in NM, we treat RT_SCOPE_NOWHERE as unset, and detect + * it based on the presence of the gateway. In other words, when adding + * a route with scope RT_SCOPE_NOWHERE (in NetworkManager) to kernel, + * the resulting scope will be either "link" or "universe" (depending + * on the gateway). + * + * Note that internally, we track @scope_inv is the inverse of scope, + * so that the default equals zero (~(RT_SCOPE_NOWHERE)). + **/ + if (route->scope_inv == 0) { + return nm_platform_route_scope_inv (!route->gateway + ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE); + } + return route->scope_inv; +} + /** * nm_platform_ip_route_normalize: * @addr_family: AF_INET or AF_INET6 @@ -3503,8 +3523,7 @@ nm_platform_ip_route_normalize (int addr_family, r4 = (NMPlatformIP4Route *) route; r4->network = nm_utils_ip4_address_clear_host_address (r4->network, r4->plen); r4->rt_source = nmp_utils_ip_config_source_round_trip_rtprot (r4->rt_source); - r4->scope_inv = nm_platform_route_scope_inv (!r4->gateway - ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE); + r4->scope_inv = _ip_route_scope_inv_get_normalized (r4); break; case AF_INET6: r6 = (NMPlatformIP6Route *) route; @@ -4814,7 +4833,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, nmp_utils_ip_config_source_round_trip_rtprot (obj->rt_source)); - h = NM_HASH_COMBINE (h, obj->scope_inv); + h = NM_HASH_COMBINE (h, _ip_route_scope_inv_get_normalized (obj)); h = NM_HASH_COMBINE (h, obj->gateway); h = NM_HASH_COMBINE (h, obj->mss); h = NM_HASH_COMBINE (h, obj->pref_src); @@ -4840,12 +4859,14 @@ nm_platform_ip4_route_hash (const NMPlatformIP4Route *obj, NMPlatformIPRouteCmpT h = NM_HASH_COMBINE (h, obj->plen); h = NM_HASH_COMBINE (h, obj->metric); h = NM_HASH_COMBINE (h, obj->gateway); - if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) + if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) { h = NM_HASH_COMBINE (h, nmp_utils_ip_config_source_round_trip_rtprot (obj->rt_source)); - else + h = NM_HASH_COMBINE (h, _ip_route_scope_inv_get_normalized (obj)); + } else { h = NM_HASH_COMBINE (h, obj->rt_source); + h = NM_HASH_COMBINE (h, obj->scope_inv); + } h = NM_HASH_COMBINE (h, obj->mss); - h = NM_HASH_COMBINE (h, obj->scope_inv); h = NM_HASH_COMBINE (h, obj->pref_src); h = NM_HASH_COMBINE (h, obj->rt_cloned); h = NM_HASH_COMBINE (h, obj->tos); @@ -4884,7 +4905,8 @@ nm_platform_ip4_route_cmp (const NMPlatformIP4Route *a, const NMPlatformIP4Route NM_CMP_FIELD (a, b, ifindex); NM_CMP_DIRECT (nmp_utils_ip_config_source_round_trip_rtprot (a->rt_source), nmp_utils_ip_config_source_round_trip_rtprot (b->rt_source)); - NM_CMP_FIELD (a, b, scope_inv); + NM_CMP_DIRECT (_ip_route_scope_inv_get_normalized (a), + _ip_route_scope_inv_get_normalized (b)); NM_CMP_FIELD (a, b, gateway); NM_CMP_FIELD (a, b, mss); NM_CMP_FIELD (a, b, pref_src); @@ -4913,10 +4935,13 @@ nm_platform_ip4_route_cmp (const NMPlatformIP4Route *a, const NMPlatformIP4Route if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) { NM_CMP_DIRECT (nmp_utils_ip_config_source_round_trip_rtprot (a->rt_source), nmp_utils_ip_config_source_round_trip_rtprot (b->rt_source)); - } else + NM_CMP_DIRECT (_ip_route_scope_inv_get_normalized (a), + _ip_route_scope_inv_get_normalized (b)); + } else { NM_CMP_FIELD (a, b, rt_source); + NM_CMP_FIELD (a, b, scope_inv); + } NM_CMP_FIELD (a, b, mss); - NM_CMP_FIELD (a, b, scope_inv); NM_CMP_FIELD (a, b, pref_src); NM_CMP_FIELD_UNSAFE (a, b, rt_cloned); NM_CMP_FIELD (a, b, tos); |