]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
networkd-manager: Fix route removals on shutdown 9981/head
authorPatrik Flykt <patrik.flykt@linux.intel.com>
Wed, 19 Sep 2018 00:32:30 +0000 (18:32 -0600)
committerPatrik Flykt <patrik.flykt@linux.intel.com>
Wed, 19 Sep 2018 19:45:18 +0000 (13:45 -0600)
In order to shut down networkd properly, the delegated routes added
need to be removed properly, and as error reporting is wanted, the
network link is needed in the debug output.

Solve this by calling manager_dhcp6_prefix_remove_all(), which will
remove each prefix stored in the Manager structure, and while doing
that reference each link so that it isn't freed before the route
removal callback is called. This in turn causes the network link to
be referenced once more, and an explicit hashmap_remove() must be
called to remove the network link from the m->links hashmap.

Also, since the registered callback is not called when the DHCPv6
client is stopped with sd_dhcp6_client_stop(), an explicit call
to dhcp6_lease_pd_prefix_lost() needs to be made to clean up any
unreachable routes set up for the delegated prefixes.

src/network/networkd-dhcp6.c
src/network/networkd-link.h
src/network/networkd-manager.c

index c044c02528871b51242440a75c2b530de2be49d6..518d3e8f1ff52ba58f6096b1a1f1faa8c3b6a22a 100644 (file)
@@ -117,7 +117,7 @@ static int dhcp6_route_remove_cb(sd_netlink *nl, sd_netlink_message *m,
         return 0;
 }
 
-static int dhcp6_lease_pd_prefix_lost(sd_dhcp6_client *client, Link* link) {
+int dhcp6_lease_pd_prefix_lost(sd_dhcp6_client *client, Link* link) {
         int r;
         sd_dhcp6_lease *lease;
         union in_addr_union pd_prefix;
index dcf722a63dca70764d22d39193781e0cbf4b57e8..b686011da405a773aff61d7a21a1be9e42b5cc55 100644 (file)
@@ -165,6 +165,7 @@ int dhcp4_set_client_identifier(Link *link);
 int dhcp4_set_promote_secondaries(Link *link);
 int dhcp6_configure(Link *link);
 int dhcp6_request_address(Link *link, int ir);
+int dhcp6_lease_pd_prefix_lost(sd_dhcp6_client *client, Link* link);
 
 const char* link_state_to_string(LinkState s) _const_;
 LinkState link_state_from_string(const char *s) _pure_;
index 73c4cd95a7a6fe58d1d7ba85d1ee98807480590f..bdb1aacf7fdf9d42c3f6d6f8fe24a61775cd2f0d 100644 (file)
@@ -1248,6 +1248,7 @@ static int dhcp6_route_add_callback(sd_netlink *nl, sd_netlink_message *m,
         if (r < 0 && r != -EEXIST)
                 log_link_debug_errno(l, r, "Received error adding DHCPv6 Prefix Delegation route: %m");
 
+        l = link_unref(l);
 
         return 0;
 }
@@ -1273,6 +1274,8 @@ int manager_dhcp6_prefix_add(Manager *m, struct in6_addr *addr, Link *link) {
         (void) in_addr_to_string(AF_INET6, (union in_addr_union *) addr, &buf);
         log_link_debug(link, "Adding prefix route %s/64", strnull(buf));
 
+        link = link_ref(link);
+
         return hashmap_put(m->dhcp6_prefixes, addr, link);
 }
 
@@ -1285,6 +1288,7 @@ static int dhcp6_route_remove_callback(sd_netlink *nl, sd_netlink_message *m,
         if (r < 0)
                 log_link_debug_errno(l, r, "Received error on DHCPv6 Prefix Delegation route removal: %m");
 
+        l = link_unref(l);
 
         return 0;
 }
@@ -1316,6 +1320,8 @@ int manager_dhcp6_prefix_remove(Manager *m, struct in6_addr *addr) {
         (void) in_addr_to_string(AF_INET6, (union in_addr_union *) addr, &buf);
         log_link_debug(l, "Removing prefix route %s/64", strnull(buf));
 
+        l = link_ref(l);
+
         return 0;
 }
 
@@ -1438,11 +1444,18 @@ void manager_free(Manager *m) {
                 network_free(network);
 
         while ((link = hashmap_first(m->dhcp6_prefixes)))
-                link_unref(link);
+                manager_dhcp6_prefix_remove_all(m, link);
         hashmap_free(m->dhcp6_prefixes);
 
-        while ((link = hashmap_first(m->links)))
+        while ((link = hashmap_first(m->links))) {
+                if (link->dhcp6_client)
+                        (void) dhcp6_lease_pd_prefix_lost(link->dhcp6_client,
+                                                          link);
+
+                hashmap_remove(m->links, INT_TO_PTR(link->ifindex));
+
                 link_unref(link);
+        }
         hashmap_free(m->links);
 
         set_free(m->links_requesting_uuid);