]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/network/networkd-dhcp6.c
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / network / networkd-dhcp6.c
index d407b31b78e9d8a145a879e972ffcec8481751a4..e5df3d22b169db279fd84e9a7c1316b278a3db0c 100644 (file)
@@ -1,5 +1,4 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
+/* SPDX-License-Identifier: LGPL-2.1+ */
 /***
   This file is part of systemd.
 
 
 #include "sd-dhcp6-client.h"
 
+#include "hostname-util.h"
 #include "network-internal.h"
 #include "networkd-link.h"
+#include "networkd-manager.h"
 
 static int dhcp6_lease_address_acquired(sd_dhcp6_client *client, Link *link);
 
@@ -62,10 +63,15 @@ static int dhcp6_address_handler(sd_netlink *rtnl, sd_netlink_message *m,
         return 1;
 }
 
-static int dhcp6_address_change(Link *link, struct in6_addr *ip6_addr,
-                                uint32_t lifetime_preferred, uint32_t lifetime_valid) {
-        int r;
+static int dhcp6_address_change(
+                Link *link,
+                struct in6_addr *ip6_addr,
+                uint32_t lifetime_preferred,
+                uint32_t lifetime_valid) {
+
         _cleanup_address_free_ Address *addr = NULL;
+        char buffer[INET6_ADDRSTRLEN];
+        int r;
 
         r = address_new(&addr);
         if (r < 0)
@@ -81,8 +87,8 @@ static int dhcp6_address_change(Link *link, struct in6_addr *ip6_addr,
         addr->cinfo.ifa_valid = lifetime_valid;
 
         log_link_info(link,
-                      "DHCPv6 address "SD_NDISC_ADDRESS_FORMAT_STR"/%d timeout preferred %d valid %d",
-                      SD_NDISC_ADDRESS_FORMAT_VAL(addr->in_addr.in6),
+                      "DHCPv6 address %s/%d timeout preferred %d valid %d",
+                      inet_ntop(AF_INET6, &addr->in_addr.in6, buffer, sizeof(buffer)),
                       addr->prefixlen, lifetime_preferred, lifetime_valid);
 
         r = address_configure(addr, link, dhcp6_address_handler, true);
@@ -105,8 +111,8 @@ static int dhcp6_lease_address_acquired(sd_dhcp6_client *client, Link *link) {
         sd_dhcp6_lease_reset_address_iter(lease);
 
         while (sd_dhcp6_lease_get_address(lease, &ip6_addr,
-                                                &lifetime_preferred,
-                                                &lifetime_valid) >= 0) {
+                                                 &lifetime_preferred,
+                                                 &lifetime_valid) >= 0) {
 
                 r = dhcp6_address_change(link, &ip6_addr, lifetime_preferred, lifetime_valid);
                 if (r < 0)
@@ -122,7 +128,6 @@ static void dhcp6_handler(sd_dhcp6_client *client, int event, void *userdata) {
 
         assert(link);
         assert(link->network);
-        assert(link->manager);
 
         if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
                 return;
@@ -166,19 +171,13 @@ static void dhcp6_handler(sd_dhcp6_client *client, int event, void *userdata) {
         link_check_ready(link);
 }
 
-int dhcp6_request_address(Link *link) {
+int dhcp6_request_address(Link *link, int ir) {
         int r, inf_req;
         bool running;
 
         assert(link);
         assert(link->dhcp6_client);
-
-        r = sd_dhcp6_client_get_information_request(link->dhcp6_client, &inf_req);
-        if (r < 0)
-                return r;
-
-        if (!inf_req)
-                return 0;
+        assert(in_addr_is_link_local(AF_INET6, (const union in_addr_union*)&link->ipv6ll_address) > 0);
 
         r = sd_dhcp6_client_is_running(link->dhcp6_client);
         if (r < 0)
@@ -187,30 +186,65 @@ int dhcp6_request_address(Link *link) {
                 running = !!r;
 
         if (running) {
+                r = sd_dhcp6_client_get_information_request(link->dhcp6_client, &inf_req);
+                if (r < 0)
+                        return r;
+
+                if (inf_req == ir)
+                        return 0;
+
                 r = sd_dhcp6_client_stop(link->dhcp6_client);
                 if (r < 0)
                         return r;
+        } else {
+                r = sd_dhcp6_client_set_local_address(link->dhcp6_client, &link->ipv6ll_address);
+                if (r < 0)
+                        return r;
         }
 
-        r = sd_dhcp6_client_set_information_request(link->dhcp6_client, false);
+        r = sd_dhcp6_client_set_information_request(link->dhcp6_client, ir);
         if (r < 0)
                 return r;
 
-        if (running) {
-                r = sd_dhcp6_client_start(link->dhcp6_client);
-                if (r < 0)
+        r = sd_dhcp6_client_start(link->dhcp6_client);
+        if (r < 0)
+                return r;
+
+        return 0;
+}
+
+static int dhcp6_set_hostname(sd_dhcp6_client *client, Link *link) {
+        _cleanup_free_ char *hostname = NULL;
+        const char *hn;
+        int r;
+
+        assert(link);
+
+        if (!link->network->dhcp_send_hostname)
+                hn = NULL;
+        else if (link->network->dhcp_hostname)
+                hn = link->network->dhcp_hostname;
+        else {
+                r = gethostname_strict(&hostname);
+                if (r < 0 && r != -ENXIO) /* ENXIO: no hostname set or hostname is "localhost" */
                         return r;
+
+                hn = hostname;
         }
 
-        return 0;
+        return sd_dhcp6_client_set_fqdn(client, hn);
 }
 
 int dhcp6_configure(Link *link) {
         sd_dhcp6_client *client = NULL;
         int r;
+        const DUID *duid;
 
         assert(link);
 
+        if (link->dhcp6_client)
+                return 0;
+
         r = sd_dhcp6_client_new(&client);
         if (r < 0)
                 return r;
@@ -219,17 +253,30 @@ int dhcp6_configure(Link *link) {
         if (r < 0)
                 goto error;
 
-        r = sd_dhcp6_client_set_information_request(client, true);
-        if (r < 0)
-                return r;
-
         r = sd_dhcp6_client_set_mac(client,
                                     (const uint8_t *) &link->mac,
                                     sizeof (link->mac), ARPHRD_ETHER);
         if (r < 0)
                 goto error;
 
-        r = sd_dhcp6_client_set_index(client, link->ifindex);
+        r = sd_dhcp6_client_set_iaid(client, link->network->iaid);
+        if (r < 0)
+                goto error;
+
+        duid = link_duid(link);
+        r = sd_dhcp6_client_set_duid(client,
+                                     duid->type,
+                                     duid->raw_data_len > 0 ? duid->raw_data : NULL,
+                                     duid->raw_data_len);
+        if (r < 0)
+                goto error;
+
+        r = dhcp6_set_hostname(client, link);
+        log_link_warning(link, "dhcp6_set_hostname: %d", r);
+        if (r < 0)
+                return r;
+
+        r = sd_dhcp6_client_set_ifindex(client, link->ifindex);
         if (r < 0)
                 goto error;