]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
networkd-dhcp6: Request prefix delegation for a new link 10257/head
authorPatrik Flykt <patrik.flykt@linux.intel.com>
Tue, 2 Oct 2018 18:29:09 +0000 (12:29 -0600)
committerPatrik Flykt <patrik.flykt@linux.intel.com>
Tue, 2 Oct 2018 18:32:46 +0000 (12:32 -0600)
Request prefix delegation for a new downstream link that is enabled
after any number of upstream DHCPv6 links. Submit the request after
the link has been configured with a link-local address.

If the upstream DHCPv6 client has already been configured to request
prefixes, attempt to re-assign any possible prefixes between the
already existing links and the new one. If no prefixes are yet
acquired, nothing will happen right away and any prefixes will be
distributed after a reply from the DHCPv6 server.

If none of the already existing downstream links have requested
DHCPv6 prefixes to be assigned, enable prefix delegation for each
client and restart them one by one if they are already running. This
causes the DHCPv6 clients to re-acquire addresses and prefixes and
to re-distribute them to all links when receiving an updated
response from their respective DHCPv6 servers. If the DHCPv6 client
in question was not already running, it is set to request prefixes
but not restarted.

When an error occurs while setting or restarting the DHCPv6 client,
log the incident and move over to the next link.

Fixes #9758.

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

index 1a033c116c8c31b5c99078f9de77521c22bf6f88..82f49e5ac07f11f17838e87208ec3aa3ea7b386e 100644 (file)
@@ -346,6 +346,70 @@ static int dhcp6_lease_pd_prefix_acquired(sd_dhcp6_client *client, Link *link) {
         return 0;
 }
 
+int dhcp6_request_prefix_delegation(Link *link) {
+        Link *l;
+        Iterator i;
+
+        assert_return(link, -EINVAL);
+        assert_return(link->manager, -EOPNOTSUPP);
+
+        if (dhcp6_get_prefix_delegation(link) <= 0)
+                return 0;
+
+        log_link_debug(link, "Requesting DHCPv6 prefixes to be delegated for new link");
+
+        HASHMAP_FOREACH(l, link->manager->links, i) {
+                int r, enabled;
+
+                if (l == link)
+                        continue;
+
+                if (!l->dhcp6_client)
+                        continue;
+
+                r = sd_dhcp6_client_get_prefix_delegation(l->dhcp6_client, &enabled);
+                if (r < 0) {
+                        log_link_warning_errno(l, r, "Cannot get prefix delegation when adding new link");
+                        continue;
+                }
+
+                if (enabled == 0) {
+                        r = sd_dhcp6_client_set_prefix_delegation(l->dhcp6_client, 1);
+                        if (r < 0) {
+                                log_link_warning_errno(l, r, "Cannot enable prefix delegation when adding new link");
+                                continue;
+                        }
+                }
+
+                r = sd_dhcp6_client_is_running(l->dhcp6_client);
+                if (r <= 0)
+                        continue;
+
+                if (enabled != 0) {
+                        log_link_debug(l, "Requesting re-assignment of delegated prefixes after adding new link");
+                        (void) dhcp6_lease_pd_prefix_acquired(l->dhcp6_client, l);
+
+                        continue;
+                }
+
+                r = sd_dhcp6_client_stop(l->dhcp6_client);
+                if (r < 0) {
+                        log_link_warning_errno(l, r, "Cannot stop DHCPv6 prefix delegation client after adding new link");
+                        continue;
+                }
+
+                r = sd_dhcp6_client_start(l->dhcp6_client);
+                if (r < 0) {
+                        log_link_warning_errno(l, r, "Cannot restart DHCPv6 prefix delegation client after adding new link");
+                        continue;
+                }
+
+                log_link_debug(l, "Restarted DHCPv6 client to acquire prefix delegations after adding new link");
+        }
+
+        return 0;
+}
+
 static int dhcp6_address_handler(sd_netlink *rtnl, sd_netlink_message *m,
                                  void *userdata) {
         _cleanup_(link_unrefp) Link *link = userdata;
index 9b555984826a6a2738d3a58730ed8d5442feef44..213c388be4cfde0c9248caef63acd4d7d0c57e2f 100644 (file)
@@ -1662,6 +1662,8 @@ static int link_acquire_ipv6_conf(Link *link) {
                         return log_link_warning_errno(link, r, "Could not start IPv6 Router Advertisement: %m");
         }
 
+        (void) dhcp6_request_prefix_delegation(link);
+
         return 0;
 }
 
index b686011da405a773aff61d7a21a1be9e42b5cc55..033cca15762e8c917aa946371e8cb913704c614b 100644 (file)
@@ -163,6 +163,7 @@ int ipv4ll_configure(Link *link);
 int dhcp4_configure(Link *link);
 int dhcp4_set_client_identifier(Link *link);
 int dhcp4_set_promote_secondaries(Link *link);
+int dhcp6_request_prefix_delegation(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);