diff options
author | Thomas Haller <thaller@redhat.com> | 2014-01-23 09:11:19 +0100 |
---|---|---|
committer | Dan Williams <dcbw@redhat.com> | 2014-01-24 09:42:52 -0600 |
commit | 8959b6dbcba24c922ec77d09424cd441ec1c95f9 (patch) | |
tree | b94ea95a534ca6925a9f9400c778cad0089d764b | |
parent | c8d7a06d64960ba5e028aaff6b9b9b280a84dad2 (diff) |
core/platform: sort routes before adding them in nm_platform_ipX_route_sync()
A gateway route can only be added, if there exists a device route
for that gateway. Therefore, nm_platform_ip4_route_sync() and
nm_platform_ip6_route_sync() has to add the device routes first,
before adding gateway routes.
Note: usually for all configured addresses, there is also a device
route for the subnet added by the kernel. This means, NM must first
configure the addresses before route_sync, so that these implicit device
routes already exist -- this is however already done correctly.
Signed-off-by: Thomas Haller <thaller@redhat.com>
-rw-r--r-- | src/platform/nm-platform.c | 80 |
1 files changed, 48 insertions, 32 deletions
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index 179b6eae68..ac24009548 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -1607,7 +1607,7 @@ nm_platform_ip4_route_sync (int ifindex, const GArray *known_routes) NMPlatformIP4Route *route; const NMPlatformIP4Route *known_route; gboolean success; - int i; + int i, i_type; /* Delete unknown routes */ routes = nm_platform_ip4_route_get_all (ifindex, FALSE); @@ -1624,21 +1624,29 @@ nm_platform_ip4_route_sync (int ifindex, const GArray *known_routes) } /* Add missing routes */ - for (i = 0, success = TRUE; i < known_routes->len && success; i++) { - known_route = &g_array_index (known_routes, NMPlatformIP4Route, i); - - /* Ignore routes that already exist */ - if (!array_contains_ip4_route (routes, known_route)) { - success = nm_platform_ip4_route_add (ifindex, - known_route->network, - known_route->plen, - known_route->gateway, - known_route->metric, - known_route->mss); - if (!success && known_route->source < NM_PLATFORM_SOURCE_USER) { - nm_log_dbg (LOGD_PLATFORM, "ignore error adding IPv4 route to kernel: %s", - nm_platform_ip4_route_to_string (known_route)); - success = TRUE; + for (i_type = 0, success = TRUE; i_type < 2 && success; i_type++) { + for (i = 0; i < known_routes->len && success; i++) { + known_route = &g_array_index (known_routes, NMPlatformIP4Route, i); + + if ((known_route->gateway == 0) ^ (i_type != 0)) { + /* Make two runs over the list of routes. On the first, only add + * device routes, on the second the others (gateway routes). */ + continue; + } + + /* Ignore routes that already exist */ + if (!array_contains_ip4_route (routes, known_route)) { + success = nm_platform_ip4_route_add (ifindex, + known_route->network, + known_route->plen, + known_route->gateway, + known_route->metric, + known_route->mss); + if (!success && known_route->source < NM_PLATFORM_SOURCE_USER) { + nm_log_dbg (LOGD_PLATFORM, "ignore error adding IPv4 route to kernel: %s", + nm_platform_ip4_route_to_string (known_route)); + success = TRUE; + } } } } @@ -1665,7 +1673,7 @@ nm_platform_ip6_route_sync (int ifindex, const GArray *known_routes) NMPlatformIP6Route *route; const NMPlatformIP6Route *known_route; gboolean success; - int i; + int i, i_type; /* Delete unknown routes */ routes = nm_platform_ip6_route_get_all (ifindex, FALSE); @@ -1683,21 +1691,29 @@ nm_platform_ip6_route_sync (int ifindex, const GArray *known_routes) } /* Add missing routes */ - for (i = 0, success = TRUE; i < known_routes->len && success; i++) { - known_route = &g_array_index (known_routes, NMPlatformIP6Route, i); - - /* Ignore routes that already exist */ - if (!array_contains_ip6_route (routes, known_route)) { - success = nm_platform_ip6_route_add (ifindex, - known_route->network, - known_route->plen, - known_route->gateway, - known_route->metric, - known_route->mss); - if (!success && known_route->source < NM_PLATFORM_SOURCE_USER) { - nm_log_dbg (LOGD_PLATFORM, "ignore error adding IPv6 route to kernel: %s", - nm_platform_ip6_route_to_string (known_route)); - success = TRUE; + for (i_type = 0, success = TRUE; i_type < 2 && success; i_type++) { + for (i = 0; i < known_routes->len && success; i++) { + known_route = &g_array_index (known_routes, NMPlatformIP6Route, i); + + if (IN6_IS_ADDR_UNSPECIFIED (&known_route->gateway) ^ (i_type != 0)) { + /* Make two runs over the list of routes. On the first, only add + * device routes, on the second the others (gateway routes). */ + continue; + } + + /* Ignore routes that already exist */ + if (!array_contains_ip6_route (routes, known_route)) { + success = nm_platform_ip6_route_add (ifindex, + known_route->network, + known_route->plen, + known_route->gateway, + known_route->metric, + known_route->mss); + if (!success && known_route->source < NM_PLATFORM_SOURCE_USER) { + nm_log_dbg (LOGD_PLATFORM, "ignore error adding IPv6 route to kernel: %s", + nm_platform_ip6_route_to_string (known_route)); + success = TRUE; + } } } } |