]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
networkd: don't remove route 10597/head
authorTobias Jungel <tobias.jungel@bisdn.de>
Tue, 6 Nov 2018 12:28:12 +0000 (13:28 +0100)
committerTobias Jungel <tobias.jungel@bisdn.de>
Tue, 6 Nov 2018 12:28:12 +0000 (13:28 +0100)
In case networkd is restarted this prevents a removal of an already existing
route that would be configured using networkd. With the proposed changes the
route will be kept on the interface without removing. This happens only on
physical hosts or VMs since networkd handles interface configuration slightly
different in containers.

src/network/networkd-link.c
src/network/networkd-route.c
src/network/networkd-route.h

index 6da881c1d310910b79ca1f79756e6f7fcd507d27..b112b13eedd4d961fd243e98374ffa3e7f54aab3 100644 (file)
@@ -2634,6 +2634,22 @@ static bool link_is_static_address_configured(Link *link, Address *address) {
         return false;
 }
 
+static bool link_is_static_route_configured(Link *link, Route *route) {
+        Route *net_route;
+
+        assert(link);
+        assert(route);
+
+        if (!link->network)
+                return false;
+
+        LIST_FOREACH(routes, net_route, link->network->static_routes)
+                if (route_equal(net_route, route))
+                        return true;
+
+        return false;
+}
+
 static int link_drop_foreign_config(Link *link) {
         Address *address;
         Route *route;
@@ -2661,9 +2677,15 @@ static int link_drop_foreign_config(Link *link) {
                 if (route->protocol == RTPROT_KERNEL)
                         continue;
 
-                r = route_remove(route, link, link_route_remove_handler);
-                if (r < 0)
-                        return r;
+                if (link_is_static_route_configured(link, route)) {
+                        r = route_add(link, route->family, &route->dst, route->dst_prefixlen, route->tos, route->priority, route->table, NULL);
+                        if (r < 0)
+                                return r;
+                } else {
+                        r = route_remove(route, link, link_route_remove_handler);
+                        if (r < 0)
+                                return r;
+                }
         }
 
         return 0;
index 529d942f1534b8e89fc8fb4a8f4147391b3fef3a..e8cde66befb9462b911fc112da74e21bb99d0314 100644 (file)
@@ -201,6 +201,16 @@ static const struct hash_ops route_hash_ops = {
         .compare = route_compare_func
 };
 
+bool route_equal(Route *r1, Route *r2) {
+        if (r1 == r2)
+                return true;
+
+        if (!r1 || !r2)
+                return false;
+
+        return route_compare_func(r1, r2) == 0;
+}
+
 int route_get(Link *link,
               int family,
               const union in_addr_union *dst,
index 7283f48304c88b963c5454cb06ba8bbfe71063fd..fe000d61b88adc4619ebbd3ef1ee0d11db90a6eb 100644 (file)
@@ -52,6 +52,7 @@ int route_get(Link *link, int family, const union in_addr_union *dst, unsigned c
 int route_add(Link *link, int family, const union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, uint32_t table, Route **ret);
 int route_add_foreign(Link *link, int family, const union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, uint32_t table, Route **ret);
 void route_update(Route *route, const union in_addr_union *src, unsigned char src_prefixlen, const union in_addr_union *gw, const union in_addr_union *prefsrc, unsigned char scope, unsigned char protocol, unsigned char type);
+bool route_equal(Route *r1, Route *r2);
 
 int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdata);