]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/network/networkd-dhcp4.c
DHCP DUID, IAID configuration options
[thirdparty/systemd.git] / src / network / networkd-dhcp4.c
index 04f04df117698836b11d0b7fe807e17c6ae5ea79..0589ebf22752ff380088620ed02265ab47aaf4b6 100644 (file)
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
 /***
   This file is part of systemd.
 
 #include <netinet/ether.h>
 #include <linux/if.h>
 
+#include "alloc-util.h"
+#include "dhcp-lease-internal.h"
 #include "hostname-util.h"
-#include "networkd-link.h"
 #include "network-internal.h"
-#include "dhcp-lease-internal.h"
+#include "networkd-link.h"
 
 static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m,
                                void *userdata) {
@@ -33,9 +32,9 @@ static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m,
         int r;
 
         assert(link);
-        assert(link->dhcp4_messages);
+        assert(link->dhcp4_messages > 0);
 
-        link->dhcp4_messages --;
+        link->dhcp4_messages--;
 
         r = sd_netlink_message_get_errno(m);
         if (r < 0 && r != -EEXIST) {
@@ -43,9 +42,9 @@ static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m,
                 link_enter_failed(link);
         }
 
-        if (!link->dhcp4_messages) {
+        if (link->dhcp4_messages == 0) {
                 link->dhcp4_configured = true;
-                link_client_handler(link);
+                link_check_ready(link);
         }
 
         return 1;
@@ -53,7 +52,7 @@ static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m,
 
 static int link_set_dhcp_routes(Link *link) {
         struct in_addr gateway;
-        struct sd_dhcp_route *static_routes;
+        _cleanup_free_ sd_dhcp_route **static_routes = NULL;
         int r, n, i;
 
         assert(link);
@@ -72,11 +71,13 @@ static int link_set_dhcp_routes(Link *link) {
                 if (r < 0)
                         return log_link_warning_errno(link, r, "DHCP error: could not get address: %m");
 
-                r = route_new_dynamic(&route, RTPROT_DHCP);
+                r = route_new(&route);
                 if (r < 0)
                         return log_link_error_errno(link, r, "Could not allocate route: %m");
 
-                r = route_new_dynamic(&route_gw, RTPROT_DHCP);
+                route->protocol = RTPROT_DHCP;
+
+                r = route_new(&route_gw);
                 if (r < 0)
                         return log_link_error_errno(link, r,  "Could not allocate route: %m");
 
@@ -84,22 +85,23 @@ static int link_set_dhcp_routes(Link *link) {
                  * route for the gw host so that we can route no matter the
                  * netmask or existing kernel route tables. */
                 route_gw->family = AF_INET;
-                route_gw->dst_addr.in = gateway;
+                route_gw->dst.in = gateway;
                 route_gw->dst_prefixlen = 32;
-                route_gw->prefsrc_addr.in = address;
+                route_gw->prefsrc.in = address;
                 route_gw->scope = RT_SCOPE_LINK;
-                route_gw->metrics = link->network->dhcp_route_metric;
+                route_gw->protocol = RTPROT_DHCP;
+                route_gw->priority = link->network->dhcp_route_metric;
 
                 r = route_configure(route_gw, link, &dhcp4_route_handler);
                 if (r < 0)
                         return log_link_warning_errno(link, r, "Could not set host route: %m");
 
-                link->dhcp4_messages ++;
+                link->dhcp4_messages++;
 
                 route->family = AF_INET;
-                route->in_addr.in = gateway;
-                route->prefsrc_addr.in = address;
-                route->metrics = link->network->dhcp_route_metric;
+                route->gw.in = gateway;
+                route->prefsrc.in = address;
+                route->priority = link->network->dhcp_route_metric;
 
                 r = route_configure(route, link, &dhcp4_route_handler);
                 if (r < 0) {
@@ -108,7 +110,7 @@ static int link_set_dhcp_routes(Link *link) {
                         return r;
                 }
 
-                link->dhcp4_messages ++;
+                link->dhcp4_messages++;
         }
 
         n = sd_dhcp_lease_get_routes(link->dhcp_lease, &static_routes);
@@ -120,21 +122,22 @@ static int link_set_dhcp_routes(Link *link) {
         for (i = 0; i < n; i++) {
                 _cleanup_route_free_ Route *route = NULL;
 
-                r = route_new_dynamic(&route, RTPROT_DHCP);
+                r = route_new(&route);
                 if (r < 0)
                         return log_link_error_errno(link, r, "Could not allocate route: %m");
 
                 route->family = AF_INET;
-                route->in_addr.in = static_routes[i].gw_addr;
-                route->dst_addr.in = static_routes[i].dst_addr;
-                route->dst_prefixlen = static_routes[i].dst_prefixlen;
-                route->metrics = link->network->dhcp_route_metric;
+                route->protocol = RTPROT_DHCP;
+                assert_se(sd_dhcp_route_get_gateway(static_routes[i], &route->gw.in) >= 0);
+                assert_se(sd_dhcp_route_get_destination(static_routes[i], &route->dst.in) >= 0);
+                assert_se(sd_dhcp_route_get_destination_prefix_length(static_routes[i], &route->dst_prefixlen) >= 0);
+                route->priority = link->network->dhcp_route_metric;
 
                 r = route_configure(route, link, &dhcp4_route_handler);
                 if (r < 0)
                         return log_link_warning_errno(link, r, "Could not set host route: %m");
 
-                link->dhcp4_messages ++;
+                link->dhcp4_messages++;
         }
 
         return 0;
@@ -153,8 +156,8 @@ static int dhcp_lease_lost(Link *link) {
 
         log_link_warning(link, "DHCP lease lost");
 
-        if (link->network->dhcp_routes) {
-                struct sd_dhcp_route *routes;
+        if (link->network->dhcp_use_routes) {
+                _cleanup_free_ sd_dhcp_route **routes = NULL;
                 int n, i;
 
                 n = sd_dhcp_lease_get_routes(link->dhcp_lease, &routes);
@@ -162,45 +165,45 @@ static int dhcp_lease_lost(Link *link) {
                         for (i = 0; i < n; i++) {
                                 _cleanup_route_free_ Route *route = NULL;
 
-                                r = route_new_dynamic(&route, RTPROT_UNSPEC);
+                                r = route_new(&route);
                                 if (r >= 0) {
                                         route->family = AF_INET;
-                                        route->in_addr.in = routes[i].gw_addr;
-                                        route->dst_addr.in = routes[i].dst_addr;
-                                        route->dst_prefixlen = routes[i].dst_prefixlen;
+                                        assert_se(sd_dhcp_route_get_gateway(routes[i], &route->gw.in) >= 0);
+                                        assert_se(sd_dhcp_route_get_destination(routes[i], &route->dst.in) >= 0);
+                                        assert_se(sd_dhcp_route_get_destination_prefix_length(routes[i], &route->dst_prefixlen) >= 0);
 
-                                        route_drop(route, link,
-                                                   &link_route_drop_handler);
+                                        route_remove(route, link,
+                                                   &link_route_remove_handler);
                                 }
                         }
                 }
         }
 
-        r = address_new_dynamic(&address);
+        r = address_new(&address);
         if (r >= 0) {
                 r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway);
                 if (r >= 0) {
                         _cleanup_route_free_ Route *route_gw = NULL;
                         _cleanup_route_free_ Route *route = NULL;
 
-                        r = route_new_dynamic(&route_gw, RTPROT_UNSPEC);
+                        r = route_new(&route_gw);
                         if (r >= 0) {
                                 route_gw->family = AF_INET;
-                                route_gw->dst_addr.in = gateway;
+                                route_gw->dst.in = gateway;
                                 route_gw->dst_prefixlen = 32;
                                 route_gw->scope = RT_SCOPE_LINK;
 
-                                route_drop(route_gw, link,
-                                           &link_route_drop_handler);
+                                route_remove(route_gw, link,
+                                           &link_route_remove_handler);
                         }
 
-                        r = route_new_dynamic(&route, RTPROT_UNSPEC);
+                        r = route_new(&route);
                         if (r >= 0) {
                                 route->family = AF_INET;
-                                route->in_addr.in = gateway;
+                                route->gw.in = gateway;
 
-                                route_drop(route, link,
-                                           &link_route_drop_handler);
+                                route_remove(route, link,
+                                           &link_route_remove_handler);
                         }
                 }
 
@@ -214,11 +217,11 @@ static int dhcp_lease_lost(Link *link) {
                         address->in_addr.in = addr;
                         address->prefixlen = prefixlen;
 
-                        address_drop(address, link, &link_address_drop_handler);
+                        address_remove(address, link, &link_address_remove_handler);
                 }
         }
 
-        if (link->network->dhcp_mtu) {
+        if (link->network->dhcp_use_mtu) {
                 uint16_t mtu;
 
                 r = sd_dhcp_lease_get_mtu(link->dhcp_lease, &mtu);
@@ -233,11 +236,11 @@ static int dhcp_lease_lost(Link *link) {
                 }
         }
 
-        if (link->network->dhcp_hostname) {
+        if (link->network->dhcp_use_hostname) {
                 const char *hostname = NULL;
 
-                if (link->network->hostname)
-                        hostname = link->network->hostname;
+                if (link->network->dhcp_hostname)
+                        hostname = link->network->dhcp_hostname;
                 else
                         (void) sd_dhcp_lease_get_hostname(link->dhcp_lease, &hostname);
 
@@ -250,6 +253,7 @@ static int dhcp_lease_lost(Link *link) {
         }
 
         link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease);
+        link_dirty(link);
         link->dhcp4_configured = false;
 
         return 0;
@@ -267,7 +271,7 @@ static int dhcp4_address_handler(sd_netlink *rtnl, sd_netlink_message *m,
                 log_link_error_errno(link, r, "Could not set DHCPv4 address: %m");
                 link_enter_failed(link);
         } else if (r >= 0)
-                link_rtnl_process_address(rtnl, m, link->manager);
+                manager_rtnl_process_address(rtnl, m, link->manager);
 
         link_set_dhcp_routes(link);
 
@@ -288,7 +292,7 @@ static int dhcp4_update_address(Link *link,
 
         prefixlen = in_addr_netmask_to_prefixlen(netmask);
 
-        r = address_new_dynamic(&addr);
+        r = address_new(&addr);
         if (r < 0)
                 return r;
 
@@ -299,9 +303,9 @@ static int dhcp4_update_address(Link *link,
         addr->prefixlen = prefixlen;
         addr->broadcast.s_addr = address->s_addr | ~netmask->s_addr;
 
-        /* use update rather than configure so that we will update the
-         * lifetime of an existing address if it has already been configured */
-        r = address_update(addr, link, &dhcp4_address_handler);
+        /* allow reusing an existing address and simply update its lifetime
+         * in case it already exists */
+        r = address_configure(addr, link, &dhcp4_address_handler, true);
         if (r < 0)
                 return r;
 
@@ -326,6 +330,7 @@ static int dhcp_lease_renew(sd_dhcp_client *client, Link *link) {
         sd_dhcp_lease_unref(link->dhcp_lease);
         link->dhcp4_configured = false;
         link->dhcp_lease = sd_dhcp_lease_ref(lease);
+        link_dirty(link);
 
         r = sd_dhcp_lease_get_address(lease, &address);
         if (r < 0)
@@ -403,8 +408,9 @@ static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
                            NULL);
 
         link->dhcp_lease = sd_dhcp_lease_ref(lease);
+        link_dirty(link);
 
-        if (link->network->dhcp_mtu) {
+        if (link->network->dhcp_use_mtu) {
                 uint16_t mtu;
 
                 r = sd_dhcp_lease_get_mtu(lease, &mtu);
@@ -415,11 +421,11 @@ static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
                 }
         }
 
-        if (link->network->dhcp_hostname) {
+        if (link->network->dhcp_use_hostname) {
                 const char *hostname = NULL;
 
-                if (link->network->hostname)
-                        hostname = link->network->hostname;
+                if (link->network->dhcp_hostname)
+                        hostname = link->network->dhcp_hostname;
                 else
                         (void) sd_dhcp_lease_get_hostname(lease, &hostname);
 
@@ -430,7 +436,7 @@ static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
                 }
         }
 
-        if (link->network->dhcp_timezone) {
+        if (link->network->dhcp_use_timezone) {
                 const char *tz = NULL;
 
                 (void) sd_dhcp_lease_get_timezone(link->dhcp_lease, &tz);
@@ -528,9 +534,11 @@ int dhcp4_configure(Link *link) {
         assert(link->network);
         assert(link->network->dhcp & ADDRESS_FAMILY_IPV4);
 
-        r = sd_dhcp_client_new(&link->dhcp_client);
-        if (r < 0)
-                return r;
+        if (!link->dhcp_client) {
+                r = sd_dhcp_client_new(&link->dhcp_client);
+                if (r < 0)
+                        return r;
+        }
 
         r = sd_dhcp_client_attach_event(link->dhcp_client, NULL, 0);
         if (r < 0)
@@ -561,45 +569,45 @@ int dhcp4_configure(Link *link) {
                         return r;
         }
 
-        if (link->network->dhcp_mtu) {
+        if (link->network->dhcp_use_mtu) {
                 r = sd_dhcp_client_set_request_option(link->dhcp_client,
-                                                      DHCP_OPTION_INTERFACE_MTU);
+                                                      SD_DHCP_OPTION_INTERFACE_MTU);
                 if (r < 0)
                         return r;
         }
 
-        if (link->network->dhcp_routes) {
+        if (link->network->dhcp_use_routes) {
                 r = sd_dhcp_client_set_request_option(link->dhcp_client,
-                                                      DHCP_OPTION_STATIC_ROUTE);
+                                                      SD_DHCP_OPTION_STATIC_ROUTE);
                 if (r < 0)
                         return r;
                 r = sd_dhcp_client_set_request_option(link->dhcp_client,
-                                                      DHCP_OPTION_CLASSLESS_STATIC_ROUTE);
+                                                      SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE);
                 if (r < 0)
                         return r;
         }
 
-        /* Always acquire the timezone and NTP*/
-        r = sd_dhcp_client_set_request_option(link->dhcp_client, DHCP_OPTION_NTP_SERVER);
+        /* Always acquire the timezone and NTP */
+        r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_NTP_SERVER);
         if (r < 0)
                 return r;
 
-        r = sd_dhcp_client_set_request_option(link->dhcp_client, DHCP_OPTION_NEW_TZDB_TIMEZONE);
+        r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_NEW_TZDB_TIMEZONE);
         if (r < 0)
                 return r;
 
-        if (link->network->dhcp_sendhost) {
+        if (link->network->dhcp_send_hostname) {
                 _cleanup_free_ char *hostname = NULL;
                 const char *hn = NULL;
 
-                if (!link->network->hostname)  {
+                if (!link->network->dhcp_hostname) {
                         hostname = gethostname_malloc();
                         if (!hostname)
                                 return -ENOMEM;
 
                         hn = hostname;
                 } else
-                        hn = link->network->hostname;
+                        hn = link->network->dhcp_hostname;
 
                 if (!is_localhost(hn)) {
                         r = sd_dhcp_client_set_hostname(link->dhcp_client, hn);
@@ -617,7 +625,21 @@ int dhcp4_configure(Link *link) {
 
         switch (link->network->dhcp_client_identifier) {
         case DHCP_CLIENT_ID_DUID:
-                /* Library defaults to this. */
+                /* If configured, apply user specified DUID and/or IAID */
+                if (link->network->duid_type != _DUID_TYPE_INVALID)
+                        r = sd_dhcp_client_set_iaid_duid(link->dhcp_client,
+                                                         link->network->iaid,
+                                                         link->network->dhcp_duid_type,
+                                                         link->network->dhcp_duid,
+                                                         link->network->dhcp_duid_len);
+                else
+                        r = sd_dhcp_client_set_iaid_duid(link->dhcp_client,
+                                                         link->network->iaid,
+                                                         link->manager->dhcp_duid_type,
+                                                         link->manager->dhcp_duid,
+                                                         link->manager->dhcp_duid_len);
+                if (r < 0)
+                        return r;
                 break;
         case DHCP_CLIENT_ID_MAC:
                 r = sd_dhcp_client_set_client_id(link->dhcp_client,