summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2017-08-17 15:17:40 +0200
committerThomas Haller <thaller@redhat.com>2017-08-24 10:47:23 +0200
commit974ff6299633bf739a73a240797cd46ebcd0e043 (patch)
tree2805005423818cfe6e73b76fcc0c9e12c012ba46
parent69a50a50531e2d8a8b6f679c25a13a5aedb5ea9e (diff)
downloadNetworkManager-974ff6299633bf739a73a240797cd46ebcd0e043.tar.gz
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".
-rw-r--r--src/platform/nm-platform.c43
1 files changed, 34 insertions, 9 deletions
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
index f392537e2a..e906ba3bc6 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);